feat(debug): replace DebugElement with new Debug DOM
Now, using `ng.probe(element)` in the browser console returns a DebugElement when in dev mode. `ComponentFixture#debugElement` also returns a new DebugElement. Breaking Change: This is a breaking change for unit tests. The API for the DebugElement has changed. Now, there is a DebugElement or DebugNode for every node in the DOM, not only nodes with an ElementRef. `componentViewChildren` is removed, and `childNodes` is a list of ElementNodes corresponding to every child in the DOM. `query` no longer takes a scope parameter, since the entire rendered DOM is included in the `childNodes`. Before: ``` componentFixture.debugElement.componentViewChildren[0]; ``` After ``` // Depending on the DOM structure of your component, the // index may have changed or the first component child // may be a sub-child. componentFixture.debugElement.children[0]; ``` Before: ``` debugElement.query(By.css('div'), Scope.all()); ``` After: ``` debugElement.query(By.css('div')); ``` Before: ``` componentFixture.debugElement.elementRef; ``` After: ``` componentFixture.elementRef; ```
This commit is contained in:
@ -30,12 +30,12 @@ import {BrowserDomAdapter} from './browser/browser_adapter';
|
||||
import {BrowserGetTestability} from 'angular2/src/platform/browser/testability';
|
||||
import {wtfInit} from 'angular2/src/core/profile/wtf_init';
|
||||
import {EventManager, EVENT_MANAGER_PLUGINS} from "angular2/src/platform/dom/events/event_manager";
|
||||
import {ELEMENT_PROBE_PROVIDERS} from 'angular2/platform/common_dom';
|
||||
export {DOCUMENT} from 'angular2/src/platform/dom/dom_tokens';
|
||||
export {Title} from 'angular2/src/platform/browser/title';
|
||||
export {
|
||||
DebugElementViewListener,
|
||||
ELEMENT_PROBE_PROVIDERS,
|
||||
ELEMENT_PROBE_BINDINGS,
|
||||
ELEMENT_PROBE_PROVIDERS_PROD_MODE,
|
||||
inspectNativeElement,
|
||||
By
|
||||
} from 'angular2/platform/common_dom';
|
||||
@ -84,7 +84,8 @@ export const BROWSER_APP_COMMON_PROVIDERS: Array<any /*Type | Provider | any[]*/
|
||||
Testability,
|
||||
BrowserDetails,
|
||||
AnimationBuilder,
|
||||
EventManager
|
||||
EventManager,
|
||||
ELEMENT_PROBE_PROVIDERS
|
||||
]);
|
||||
|
||||
export function initDomAdapter() {
|
||||
|
@ -39,6 +39,6 @@ export class By {
|
||||
* {@example platform/dom/debug/ts/by/by.ts region='by_directive'}
|
||||
*/
|
||||
static directive(type: Type): Predicate<DebugElement> {
|
||||
return (debugElement) => { return debugElement.hasDirective(type); };
|
||||
return (debugElement) => { return debugElement.providerTokens.indexOf(type) !== -1; };
|
||||
}
|
||||
}
|
||||
|
@ -1,89 +0,0 @@
|
||||
import {CONST_EXPR, isPresent, NumberWrapper, StringWrapper} from 'angular2/src/facade/lang';
|
||||
import {MapWrapper, Map, ListWrapper} from 'angular2/src/facade/collection';
|
||||
import {Injectable, provide, Provider} from 'angular2/src/core/di';
|
||||
import {AppViewListener} from 'angular2/src/core/linker/view_listener';
|
||||
import {AppView} from 'angular2/src/core/linker/view';
|
||||
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
||||
import {DebugElement, DebugElement_} from 'angular2/src/core/debug/debug_element';
|
||||
|
||||
const NG_ID_PROPERTY = 'ngid';
|
||||
const INSPECT_GLOBAL_NAME = 'ng.probe';
|
||||
|
||||
const NG_ID_SEPARATOR = '#';
|
||||
|
||||
// Need to keep the views in a global Map so that multiple angular apps are supported
|
||||
var _allIdsByView = new Map<AppView, number>();
|
||||
var _allViewsById = new Map<number, AppView>();
|
||||
|
||||
var _nextId = 0;
|
||||
|
||||
function _setElementId(element, indices: number[]) {
|
||||
if (isPresent(element) && DOM.isElementNode(element)) {
|
||||
DOM.setData(element, NG_ID_PROPERTY, indices.join(NG_ID_SEPARATOR));
|
||||
}
|
||||
}
|
||||
|
||||
function _getElementId(element): number[] {
|
||||
var elId = DOM.getData(element, NG_ID_PROPERTY);
|
||||
if (isPresent(elId)) {
|
||||
return elId.split(NG_ID_SEPARATOR).map(partStr => NumberWrapper.parseInt(partStr, 10));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link DebugElement} for the given native DOM element, or
|
||||
* null if the given native element does not have an Angular view associated
|
||||
* with it.
|
||||
*/
|
||||
export function inspectNativeElement(element): DebugElement {
|
||||
var elId = _getElementId(element);
|
||||
if (isPresent(elId)) {
|
||||
var view = _allViewsById.get(elId[0]);
|
||||
if (isPresent(view)) {
|
||||
return new DebugElement_(view.appElements[elId[1]]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class DebugElementViewListener implements AppViewListener {
|
||||
constructor() { DOM.setGlobalVar(INSPECT_GLOBAL_NAME, inspectNativeElement); }
|
||||
|
||||
onViewCreated(view: AppView) {
|
||||
var viewId = _nextId++;
|
||||
_allViewsById.set(viewId, view);
|
||||
_allIdsByView.set(view, viewId);
|
||||
for (var i = 0; i < view.appElements.length; i++) {
|
||||
var el = view.appElements[i];
|
||||
_setElementId(el.nativeElement, [viewId, i]);
|
||||
}
|
||||
}
|
||||
|
||||
onViewDestroyed(view: AppView) {
|
||||
var viewId = _allIdsByView.get(view);
|
||||
_allIdsByView.delete(view);
|
||||
_allViewsById.delete(viewId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Providers which support debugging Angular applications (e.g. via `ng.probe`).
|
||||
*
|
||||
* ## Example
|
||||
*
|
||||
* {@example platform/dom/debug/ts/debug_element_view_listener/providers.ts region='providers'}
|
||||
*/
|
||||
export const ELEMENT_PROBE_PROVIDERS: any[] = CONST_EXPR([
|
||||
DebugElementViewListener,
|
||||
CONST_EXPR(new Provider(AppViewListener, {useExisting: DebugElementViewListener})),
|
||||
]);
|
||||
|
||||
/**
|
||||
* Use {@link ELEMENT_PROBE_PROVIDERS}.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
export const ELEMENT_PROBE_BINDINGS = ELEMENT_PROBE_PROVIDERS;
|
42
modules/angular2/src/platform/dom/debug/ng_probe.ts
Normal file
42
modules/angular2/src/platform/dom/debug/ng_probe.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import {CONST_EXPR, assertionsEnabled, isPresent} from 'angular2/src/facade/lang';
|
||||
import {Injectable, provide, Provider} from 'angular2/src/core/di';
|
||||
import {DOM} from 'angular2/src/platform/dom/dom_adapter';
|
||||
import {DebugNode, getDebugNode} from 'angular2/src/core/debug/debug_node';
|
||||
import {DomRootRenderer} from 'angular2/src/platform/dom/dom_renderer';
|
||||
import {RootRenderer} from 'angular2/core';
|
||||
import {DebugDomRootRenderer} from 'angular2/src/core/debug/debug_renderer';
|
||||
|
||||
|
||||
const INSPECT_GLOBAL_NAME = 'ng.probe';
|
||||
|
||||
/**
|
||||
* Returns a {@link DebugElement} for the given native DOM element, or
|
||||
* null if the given native element does not have an Angular view associated
|
||||
* with it.
|
||||
*/
|
||||
export function inspectNativeElement(element): DebugNode {
|
||||
return getDebugNode(element);
|
||||
}
|
||||
|
||||
function _createConditionalRootRenderer(rootRenderer) {
|
||||
if (assertionsEnabled()) {
|
||||
return _createRootRenderer(rootRenderer);
|
||||
}
|
||||
return rootRenderer;
|
||||
}
|
||||
|
||||
function _createRootRenderer(rootRenderer) {
|
||||
DOM.setGlobalVar(INSPECT_GLOBAL_NAME, inspectNativeElement);
|
||||
return new DebugDomRootRenderer(rootRenderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Providers which support debugging Angular applications (e.g. via `ng.probe`).
|
||||
*/
|
||||
export const ELEMENT_PROBE_PROVIDERS: any[] = CONST_EXPR([
|
||||
new Provider(RootRenderer,
|
||||
{useFactory: _createConditionalRootRenderer, deps: [DomRootRenderer]})
|
||||
]);
|
||||
|
||||
export const ELEMENT_PROBE_PROVIDERS_PROD_MODE: any[] = CONST_EXPR(
|
||||
[new Provider(RootRenderer, {useFactory: _createRootRenderer, deps: [DomRootRenderer]})]);
|
@ -14,7 +14,12 @@ import {
|
||||
import {BaseException, WrappedException} from 'angular2/src/facade/exceptions';
|
||||
import {DomSharedStylesHost} from './shared_styles_host';
|
||||
|
||||
import {Renderer, RootRenderer, RenderComponentType} from 'angular2/core';
|
||||
import {
|
||||
Renderer,
|
||||
RootRenderer,
|
||||
RenderComponentType,
|
||||
RenderDebugInfo
|
||||
} from 'angular2/src/core/render/api';
|
||||
|
||||
import {EventManager} from './events/event_manager';
|
||||
|
||||
@ -201,6 +206,8 @@ export class DomRenderer implements Renderer {
|
||||
}
|
||||
}
|
||||
|
||||
setElementDebugInfo(renderElement: any, info: RenderDebugInfo) {}
|
||||
|
||||
setElementClass(renderElement: any, className: string, isAdd: boolean): void {
|
||||
if (isAdd) {
|
||||
DOM.addClass(renderElement, className);
|
||||
|
Reference in New Issue
Block a user