docs(ivy): document global debugging utilities and clean up API (#34453)
Cleans up the public API of the global debugging utilities, documents them and exposes them in the API docs. PR Close #34453
This commit is contained in:
parent
d72cfc9d57
commit
471375adbe
|
@ -97,7 +97,7 @@ module.exports =
|
|||
'common/testing/index.ts',
|
||||
'common/upgrade/index.ts',
|
||||
'core/index.ts',
|
||||
'core/global.ts',
|
||||
'core/global/index.ts',
|
||||
'core/testing/index.ts',
|
||||
'elements/index.ts',
|
||||
'forms/index.ts',
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
|
@ -0,0 +1,5 @@
|
|||
Exposes a set of functions in the global namespace which are useful for debugging the current state
|
||||
of your application.
|
||||
These functions are exposed via the global `ng` "namespace" variable automatically when you import
|
||||
from `@angular/core` and run your application in development mode. These functions are not exposed
|
||||
when the application runs in a production mode.
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
// The global utilities are re-exported through here so that they get their own separate `global`
|
||||
// section in the API docs which makes it more visible that they can't be imported directly.
|
||||
export * from '../src/render3/global_utils_api';
|
|
@ -7,18 +7,18 @@
|
|||
*/
|
||||
|
||||
import {Injector} from '../di';
|
||||
import {getViewComponent} from '../render3/global_utils_api';
|
||||
import {CONTAINER_HEADER_OFFSET, LContainer, NATIVE} from '../render3/interfaces/container';
|
||||
import {TElementNode, TNode, TNodeFlags, TNodeType} from '../render3/interfaces/node';
|
||||
import {isComponentHost, isLContainer} from '../render3/interfaces/type_checks';
|
||||
import {DECLARATION_COMPONENT_VIEW, LView, PARENT, TData, TVIEW, T_HOST} from '../render3/interfaces/view';
|
||||
import {getComponent, getContext, getInjectionTokens, getInjector, getListeners, getLocalRefs, isBrowserEvents, loadLContext} from '../render3/util/discovery_utils';
|
||||
import {getComponent, getContext, getInjectionTokens, getInjector, getListeners, getLocalRefs, getOwningComponent, loadLContext} from '../render3/util/discovery_utils';
|
||||
import {INTERPOLATION_DELIMITER, renderStringify} from '../render3/util/misc_utils';
|
||||
import {getComponentLViewByIndex, getNativeByTNodeOrNull} from '../render3/util/view_utils';
|
||||
import {assertDomNode} from '../util/assert';
|
||||
import {DebugContext} from '../view/index';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @publicApi
|
||||
*/
|
||||
|
@ -217,14 +217,14 @@ class DebugNode__POST_R3__ implements DebugNode {
|
|||
get componentInstance(): any {
|
||||
const nativeElement = this.nativeNode;
|
||||
return nativeElement &&
|
||||
(getComponent(nativeElement as Element) || getViewComponent(nativeElement));
|
||||
(getComponent(nativeElement as Element) || getOwningComponent(nativeElement));
|
||||
}
|
||||
get context(): any {
|
||||
return getComponent(this.nativeNode as Element) || getContext(this.nativeNode as Element);
|
||||
}
|
||||
|
||||
get listeners(): DebugEventListener[] {
|
||||
return getListeners(this.nativeNode as Element).filter(isBrowserEvents);
|
||||
return getListeners(this.nativeNode as Element).filter(listener => listener.type === 'dom');
|
||||
}
|
||||
|
||||
get references(): {[key: string]: any;} { return getLocalRefs(this.nativeNode); }
|
||||
|
|
|
@ -16,4 +16,5 @@
|
|||
*/
|
||||
|
||||
export {markDirty} from './instructions/all';
|
||||
export {getComponent, getContext, getDebugNode, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent} from './util/discovery_utils';
|
||||
export {applyChanges} from './util/change_detection_utils';
|
||||
export {Listener, getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getOwningComponent, getRootComponents} from './util/discovery_utils';
|
||||
|
|
|
@ -15,44 +15,35 @@ import {detectChangesInternal, markViewDirty, scheduleTick, tickRootContext} fro
|
|||
/**
|
||||
* Synchronously perform change detection on a component (and possibly its sub-components).
|
||||
*
|
||||
* This function triggers change detection in a synchronous way on a component. There should
|
||||
* be very little reason to call this function directly since a preferred way to do change
|
||||
* detection is to {@link markDirty} the component and wait for the scheduler to call this method
|
||||
* at some future point in time. This is because a single user action often results in many
|
||||
* components being invalidated and calling change detection on each component synchronously
|
||||
* would be inefficient. It is better to wait until all components are marked as dirty and
|
||||
* then perform single change detection across all of the components
|
||||
* This function triggers change detection in a synchronous way on a component.
|
||||
*
|
||||
* @param component The component which the change detection should be performed on.
|
||||
*/
|
||||
export function detectChanges<T>(component: T): void {
|
||||
export function detectChanges(component: {}): void {
|
||||
const view = getComponentViewByInstance(component);
|
||||
detectChangesInternal<T>(view, component);
|
||||
detectChangesInternal(view, component);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the component as dirty (needing change detection).
|
||||
* Marks the component as dirty (needing change detection). Marking a component dirty will
|
||||
* schedule a change detection on it at some point in the future.
|
||||
*
|
||||
* Marking a component dirty will schedule a change detection on this
|
||||
* component at some point in the future. Marking an already dirty
|
||||
* component as dirty is a noop. Only one outstanding change detection
|
||||
* can be scheduled per component tree. (Two components bootstrapped with
|
||||
* separate `renderComponent` will have separate schedulers)
|
||||
*
|
||||
* When the root component is bootstrapped with `renderComponent`, a scheduler
|
||||
* can be provided.
|
||||
* Marking an already dirty component as dirty won't do anything. Only one outstanding change
|
||||
* detection can be scheduled per component tree.
|
||||
*
|
||||
* @param component Component to mark as dirty.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function markDirty<T>(component: T) {
|
||||
export function markDirty(component: {}): void {
|
||||
ngDevMode && assertDefined(component, 'component');
|
||||
const rootView = markViewDirty(getComponentViewByInstance(component)) !;
|
||||
|
||||
ngDevMode && assertDefined(rootView[CONTEXT], 'rootContext should be defined');
|
||||
scheduleTick(rootView[CONTEXT] as RootContext, RootContextFlags.DetectChanges);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to perform change detection on the whole application.
|
||||
*
|
||||
|
|
|
@ -57,8 +57,6 @@ export function ɵɵpipe(index: number, pipeName: string): any {
|
|||
* @param name Name of pipe to resolve
|
||||
* @param registry Full list of available pipes
|
||||
* @returns Matching PipeDef
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
function getPipeDef(name: string, registry: PipeDefList | null): PipeDef<any> {
|
||||
if (registry) {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {detectChanges, markDirty} from '../instructions/all';
|
||||
import {getRootComponents} from './discovery_utils';
|
||||
|
||||
/**
|
||||
* Marks a component for check (in case of OnPush components) and synchronously
|
||||
* performs change detection on the application this component belongs to.
|
||||
*
|
||||
* @param component Component to {@link ChangeDetectorRef#markForCheck mark for check}.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function applyChanges(component: {}): void {
|
||||
markDirty(component);
|
||||
getRootComponents(component).forEach(rootComponent => detectChanges(rootComponent));
|
||||
}
|
|
@ -24,31 +24,35 @@ import {getTNode, unwrapRNode} from './view_utils';
|
|||
|
||||
|
||||
/**
|
||||
* Returns the component instance associated with a given DOM host element.
|
||||
* Elements which don't represent components return `null`.
|
||||
* Retrieves the component instance associated with a given DOM element.
|
||||
*
|
||||
* @param element Host DOM element from which the component should be retrieved.
|
||||
*
|
||||
* ```
|
||||
* @usageNotes
|
||||
* Given the following DOM structure:
|
||||
* ```html
|
||||
* <my-app>
|
||||
* #VIEW
|
||||
* <div>
|
||||
* <child-comp></child-comp>
|
||||
* </div>
|
||||
* </mp-app>
|
||||
*
|
||||
* expect(getComponent(<child-comp>) instanceof ChildComponent).toBeTruthy();
|
||||
* expect(getComponent(<my-app>) instanceof MyApp).toBeTruthy();
|
||||
* </my-app>
|
||||
* ```
|
||||
* Calling `getComponent` on `<child-comp>` will return the instance of `ChildComponent`
|
||||
* associated with this DOM element.
|
||||
*
|
||||
* Calling the function on `<my-app>` will return the `MyApp` instance.
|
||||
*
|
||||
*
|
||||
* @param element DOM element from which the component should be retrieved.
|
||||
* @returns Component instance associated with the element or `null` if there
|
||||
* is no component associated with it.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function getComponent<T = {}>(element: Element): T|null {
|
||||
if (!(element instanceof Node)) throw new Error('Expecting instance of DOM Node');
|
||||
export function getComponent<T>(element: Element): T|null {
|
||||
assertDomElement(element);
|
||||
const context = loadLContext(element, false);
|
||||
if (context === null) return null;
|
||||
|
||||
|
||||
if (context.component === undefined) {
|
||||
context.component = getComponentAtNodeIndex(context.nodeIndex, context.lView);
|
||||
}
|
||||
|
@ -56,56 +60,42 @@ export function getComponent<T = {}>(element: Element): T|null {
|
|||
return context.component as T;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the component instance associated with a given DOM host element.
|
||||
* Elements which don't represent components return `null`.
|
||||
* If inside an embedded view (e.g. `*ngIf` or `*ngFor`), retrieves the context of the embedded
|
||||
* view that the element is part of. Otherwise retrieves the instance of the component whose view
|
||||
* owns the element (in this case, the result is the same as calling `getOwningComponent`).
|
||||
*
|
||||
* @param element Host DOM element from which the component should be retrieved.
|
||||
*
|
||||
* ```
|
||||
* <my-app>
|
||||
* #VIEW
|
||||
* <div>
|
||||
* <child-comp></child-comp>
|
||||
* </div>
|
||||
* </mp-app>
|
||||
*
|
||||
* expect(getComponent(<child-comp>) instanceof ChildComponent).toBeTruthy();
|
||||
* expect(getComponent(<my-app>) instanceof MyApp).toBeTruthy();
|
||||
* ```
|
||||
* @param element Element for which to get the surrounding component instance.
|
||||
* @returns Instance of the component that is around the element or null if the element isn't
|
||||
* inside any component.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function getContext<T = {}>(element: Element): T|null {
|
||||
if (!(element instanceof Node)) throw new Error('Expecting instance of DOM Node');
|
||||
export function getContext<T>(element: Element): T|null {
|
||||
assertDomElement(element);
|
||||
const context = loadLContext(element, false);
|
||||
if (context === null) return null;
|
||||
|
||||
return context.lView[CONTEXT] as T;
|
||||
return context === null ? null : context.lView[CONTEXT] as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the component instance associated with view which owns the DOM element (`null`
|
||||
* otherwise).
|
||||
* Retrieves the component instance whose view contains the DOM element.
|
||||
*
|
||||
* @param element DOM element which is owned by an existing component's view.
|
||||
* For example, if `<child-comp>` is used in the template of `<app-comp>`
|
||||
* (i.e. a `ViewChild` of `<app-comp>`), calling `getOwningComponent` on `<child-comp>`
|
||||
* would return `<app-comp>`.
|
||||
*
|
||||
* ```
|
||||
* <my-app>
|
||||
* #VIEW
|
||||
* <div>
|
||||
* <child-comp></child-comp>
|
||||
* </div>
|
||||
* </mp-app>
|
||||
*
|
||||
* expect(getViewComponent(<child-comp>) instanceof MyApp).toBeTruthy();
|
||||
* expect(getViewComponent(<my-app>)).toEqual(null);
|
||||
* ```
|
||||
* @param elementOrDir DOM element, component or directive instance
|
||||
* for which to retrieve the root components.
|
||||
* @returns Component instance whose view owns the DOM element or null if the element is not
|
||||
* part of a component view.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function getViewComponent<T = {}>(element: Element | {}): T|null {
|
||||
const context = loadLContext(element, false);
|
||||
export function getOwningComponent<T>(elementOrDir: Element | {}): T|null {
|
||||
const context = loadLContext(elementOrDir, false);
|
||||
if (context === null) return null;
|
||||
|
||||
let lView = context.lView;
|
||||
|
@ -119,27 +109,32 @@ export function getViewComponent<T = {}>(element: Element | {}): T|null {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieve all root components.
|
||||
*
|
||||
* Retrieves all root components associated with a DOM element, directive or component instance.
|
||||
* Root components are those which have been bootstrapped by Angular.
|
||||
*
|
||||
* @param target A DOM element, component or directive instance.
|
||||
* @param elementOrDir DOM element, component or directive instance
|
||||
* for which to retrieve the root components.
|
||||
* @returns Root components associated with the target object.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function getRootComponents(target: {}): any[] {
|
||||
return [...getRootContext(target).components];
|
||||
export function getRootComponents(elementOrDir: Element | {}): {}[] {
|
||||
return [...getRootContext(elementOrDir).components];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an `Injector` associated with the element, component or directive.
|
||||
* Retrieves an `Injector` associated with an element, component or directive instance.
|
||||
*
|
||||
* @param target A DOM element, component or directive instance.
|
||||
* @param elementOrDir DOM element, component or directive instance for which to
|
||||
* retrieve the injector.
|
||||
* @returns Injector associated with the element, component or directive instance.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function getInjector(target: {}): Injector {
|
||||
const context = loadLContext(target, false);
|
||||
export function getInjector(elementOrDir: Element | {}): Injector {
|
||||
const context = loadLContext(elementOrDir, false);
|
||||
if (context === null) return Injector.NULL;
|
||||
|
||||
const tNode = context.lView[TVIEW].data[context.nodeIndex] as TElementNode;
|
||||
|
@ -150,7 +145,6 @@ export function getInjector(target: {}): Injector {
|
|||
* Retrieve a set of injection tokens at a given DOM node.
|
||||
*
|
||||
* @param element Element for which the injection tokens should be retrieved.
|
||||
* @publicApi
|
||||
*/
|
||||
export function getInjectionTokens(element: Element): any[] {
|
||||
const context = loadLContext(element, false);
|
||||
|
@ -176,26 +170,43 @@ export function getInjectionTokens(element: Element): any[] {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieves directives associated with a given DOM host element.
|
||||
* Retrieves directive instances associated with a given DOM element. Does not include
|
||||
* component instances.
|
||||
*
|
||||
* @param target A DOM element, component or directive instance.
|
||||
* @usageNotes
|
||||
* Given the following DOM structure:
|
||||
* ```
|
||||
* <my-app>
|
||||
* <button my-button></button>
|
||||
* <my-comp></my-comp>
|
||||
* </my-app>
|
||||
* ```
|
||||
* Calling `getDirectives` on `<button>` will return an array with an instance of the `MyButton`
|
||||
* directive that is associated with the DOM element.
|
||||
*
|
||||
* Calling `getDirectives` on `<my-comp>` will return an empty array.
|
||||
*
|
||||
* @param element DOM element for which to get the directives.
|
||||
* @returns Array of directives associated with the element.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function getDirectives(target: {}): Array<{}> {
|
||||
const context = loadLContext(target) !;
|
||||
export function getDirectives(element: Element): {}[] {
|
||||
const context = loadLContext(element) !;
|
||||
|
||||
if (context.directives === undefined) {
|
||||
context.directives = getDirectivesAtNodeIndex(context.nodeIndex, context.lView, false);
|
||||
}
|
||||
|
||||
return context.directives || [];
|
||||
// The `directives` in this case are a named array called `LComponentView`. Clone the
|
||||
// result so we don't expose an internal data structure in the user's console.
|
||||
return context.directives === null ? [] : [...context.directives];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns LContext associated with a target passed as an argument.
|
||||
* Throws if a given target doesn't have associated LContext.
|
||||
*
|
||||
*/
|
||||
export function loadLContext(target: {}): LContext;
|
||||
export function loadLContext(target: {}, throwOnNotFound: false): LContext|null;
|
||||
|
@ -214,9 +225,8 @@ export function loadLContext(target: {}, throwOnNotFound: boolean = true): LCont
|
|||
*
|
||||
* The references are retrieved as a map of local reference name to element or directive instance.
|
||||
*
|
||||
* @param target A DOM element, component or directive instance.
|
||||
*
|
||||
* @publicApi
|
||||
* @param target DOM element, component or directive instance for which to retrieve
|
||||
* the local references.
|
||||
*/
|
||||
export function getLocalRefs(target: {}): {[key: string]: any} {
|
||||
const context = loadLContext(target, false);
|
||||
|
@ -230,17 +240,18 @@ export function getLocalRefs(target: {}): {[key: string]: any} {
|
|||
}
|
||||
|
||||
/**
|
||||
* Retrieve the host element of the component.
|
||||
* Retrieves the host element of a component or directive instance.
|
||||
* The host element is the DOM element that matched the selector of the directive.
|
||||
*
|
||||
* Use this function to retrieve the host element of the component. The host
|
||||
* element is the element which the component is associated with.
|
||||
*
|
||||
* @param directive Component or Directive for which the host element should be retrieved.
|
||||
* @param componentOrDirective Component or directive instance for which the host
|
||||
* element should be retrieved.
|
||||
* @returns Host element of the target.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function getHostElement<T>(directive: T): Element {
|
||||
return getLContext(directive) !.native as never as Element;
|
||||
export function getHostElement(componentOrDirective: {}): Element {
|
||||
return getLContext(componentOrDirective) !.native as never as Element;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -259,46 +270,61 @@ export function getRenderedText(component: any): string {
|
|||
}
|
||||
|
||||
export function loadLContextFromNode(node: Node): LContext {
|
||||
if (!(node instanceof Node)) throw new Error('Expecting instance of DOM Node');
|
||||
if (!(node instanceof Node)) throw new Error('Expecting instance of DOM Element');
|
||||
return loadLContext(node) !;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event listener configuration returned from `getListeners`.
|
||||
* @publicApi
|
||||
*/
|
||||
export interface Listener {
|
||||
/** Name of the event listener. */
|
||||
name: string;
|
||||
/** Element that the listener is bound to. */
|
||||
element: Element;
|
||||
/** Callback that is invoked when the event is triggered. */
|
||||
callback: (value: any) => any;
|
||||
useCapture: boolean|null;
|
||||
}
|
||||
|
||||
export function isBrowserEvents(listener: Listener): boolean {
|
||||
// Browser events are those which don't have `useCapture` as boolean.
|
||||
return typeof listener.useCapture === 'boolean';
|
||||
/** Whether the listener is using event capturing. */
|
||||
useCapture: boolean;
|
||||
/**
|
||||
* Type of the listener (e.g. a native DOM event or a custom @Output).
|
||||
*/
|
||||
type: 'dom'|'output';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves a list of DOM listeners.
|
||||
* Retrieves a list of event listeners associated with a DOM element. The list does include host
|
||||
* listeners, but it does not include event listeners defined outside of the Angular context
|
||||
* (e.g. through `addEventListener`).
|
||||
*
|
||||
* @usageNotes
|
||||
* Given the following DOM structure:
|
||||
* ```
|
||||
* <my-app>
|
||||
* #VIEW
|
||||
* <div (click)="doSomething()">
|
||||
* </div>
|
||||
* </mp-app>
|
||||
* <div (click)="doSomething()"></div>
|
||||
* </my-app>
|
||||
*
|
||||
* expect(getListeners(<div>)).toEqual({
|
||||
* ```
|
||||
* Calling `getListeners` on `<div>` will return an object that looks as follows:
|
||||
* ```
|
||||
* {
|
||||
* name: 'click',
|
||||
* element: <div>,
|
||||
* callback: () => doSomething(),
|
||||
* useCapture: false
|
||||
* });
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param element Element for which the DOM listeners should be retrieved.
|
||||
* @returns Array of event listeners on the DOM element.
|
||||
*
|
||||
* @publicApi
|
||||
* @globalApi ng
|
||||
*/
|
||||
export function getListeners(element: Element): Listener[] {
|
||||
if (!(element instanceof Node)) throw new Error('Expecting instance of DOM Node');
|
||||
assertDomElement(element);
|
||||
const lContext = loadLContext(element, false);
|
||||
if (lContext === null) return [];
|
||||
|
||||
|
@ -319,11 +345,11 @@ export function getListeners(element: Element): Listener[] {
|
|||
// if useCaptureOrIndx is boolean then report it as is.
|
||||
// if useCaptureOrIndx is positive number then it in unsubscribe method
|
||||
// if useCaptureOrIndx is negative number then it is a Subscription
|
||||
const useCapture = typeof useCaptureOrIndx === 'boolean' ?
|
||||
useCaptureOrIndx :
|
||||
(useCaptureOrIndx >= 0 ? false : null);
|
||||
const type =
|
||||
(typeof useCaptureOrIndx === 'boolean' || useCaptureOrIndx >= 0) ? 'dom' : 'output';
|
||||
const useCapture = typeof useCaptureOrIndx === 'boolean' ? useCaptureOrIndx : false;
|
||||
if (element == listenerElement) {
|
||||
listeners.push({element, name, callback, useCapture});
|
||||
listeners.push({element, name, callback, useCapture, type});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -350,10 +376,8 @@ function isDirectiveDefHack(obj: any): obj is DirectiveDef<any> {
|
|||
* Returns the attached `DebugNode` instance for an element in the DOM.
|
||||
*
|
||||
* @param element DOM element which is owned by an existing component's view.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function getDebugNode(element: Node): DebugNode|null {
|
||||
export function getDebugNode(element: Element): DebugNode|null {
|
||||
let debugNode: DebugNode|null = null;
|
||||
|
||||
const lContext = loadLContextFromNode(element);
|
||||
|
@ -377,7 +401,7 @@ export function getDebugNode(element: Node): DebugNode|null {
|
|||
* NOTE: `LView` is a private and should not be leaked outside.
|
||||
* Don't export this method to `ng.*` on window.
|
||||
*
|
||||
* @param target Component or Element instance.
|
||||
* @param target DOM element or component instance for which to retrieve the LView.
|
||||
*/
|
||||
export function getComponentLView(target: any): LView {
|
||||
const lContext = loadLContext(target);
|
||||
|
@ -387,3 +411,10 @@ export function getComponentLView(target: any): LView {
|
|||
ngDevMode && assertLView(componentLView);
|
||||
return componentLView;
|
||||
}
|
||||
|
||||
/** Asserts that a value is a DOM Element. */
|
||||
function assertDomElement(value: any) {
|
||||
if (typeof Element !== 'undefined' && !(value instanceof Element)) {
|
||||
throw new Error('Expecting instance of DOM Element');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
*/
|
||||
import {assertDefined} from '../../util/assert';
|
||||
import {global} from '../../util/global';
|
||||
import {getComponent, getContext, getDebugNode, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent, markDirty} from '../global_utils_api';
|
||||
import {markDirty} from '../instructions/all';
|
||||
|
||||
import {applyChanges} from './change_detection_utils';
|
||||
import {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getOwningComponent, getRootComponents} from './discovery_utils';
|
||||
|
||||
|
||||
|
||||
|
@ -42,13 +45,13 @@ export function publishDefaultGlobalUtils() {
|
|||
publishGlobalUtil('getComponent', getComponent);
|
||||
publishGlobalUtil('getContext', getContext);
|
||||
publishGlobalUtil('getListeners', getListeners);
|
||||
publishGlobalUtil('getViewComponent', getViewComponent);
|
||||
publishGlobalUtil('getOwningComponent', getOwningComponent);
|
||||
publishGlobalUtil('getHostElement', getHostElement);
|
||||
publishGlobalUtil('getInjector', getInjector);
|
||||
publishGlobalUtil('getRootComponents', getRootComponents);
|
||||
publishGlobalUtil('getDirectives', getDirectives);
|
||||
publishGlobalUtil('getDebugNode', getDebugNode);
|
||||
publishGlobalUtil('markDirty', markDirty);
|
||||
publishGlobalUtil('applyChanges', applyChanges);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import {expect} from '@angular/core/testing/src/testing_internal';
|
|||
import {onlyInIvy} from '@angular/private/testing';
|
||||
|
||||
import {getHostElement, markDirty} from '../../src/render3/index';
|
||||
import {getComponent, getComponentLView, getContext, getDebugNode, getDirectives, getInjectionTokens, getInjector, getListeners, getLocalRefs, getRootComponents, getViewComponent, loadLContext} from '../../src/render3/util/discovery_utils';
|
||||
import {getComponent, getComponentLView, getContext, getDebugNode, getDirectives, getInjectionTokens, getInjector, getListeners, getLocalRefs, getOwningComponent, getRootComponents, loadLContext} from '../../src/render3/util/discovery_utils';
|
||||
|
||||
onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
||||
let fixture: ComponentFixture<MyApp>;
|
||||
|
@ -81,8 +81,8 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
|||
expect(getComponent(p[0])).toEqual(null);
|
||||
});
|
||||
it('should throw when called on non-element', () => {
|
||||
expect(() => getComponent(dirA[0] as any)).toThrowError(/Expecting instance of DOM Node/);
|
||||
expect(() => getComponent(dirA[1] as any)).toThrowError(/Expecting instance of DOM Node/);
|
||||
expect(() => getComponent(dirA[0] as any)).toThrowError(/Expecting instance of DOM Element/);
|
||||
expect(() => getComponent(dirA[1] as any)).toThrowError(/Expecting instance of DOM Element/);
|
||||
});
|
||||
it('should return component from element', () => {
|
||||
expect(getComponent<MyApp>(fixture.nativeElement)).toEqual(myApp);
|
||||
|
@ -107,8 +107,8 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
|||
|
||||
describe('getContext', () => {
|
||||
it('should throw when called on non-element', () => {
|
||||
expect(() => getContext(dirA[0] as any)).toThrowError(/Expecting instance of DOM Node/);
|
||||
expect(() => getContext(dirA[1] as any)).toThrowError(/Expecting instance of DOM Node/);
|
||||
expect(() => getContext(dirA[0] as any)).toThrowError(/Expecting instance of DOM Element/);
|
||||
expect(() => getContext(dirA[1] as any)).toThrowError(/Expecting instance of DOM Element/);
|
||||
});
|
||||
it('should return context from element', () => {
|
||||
expect(getContext<MyApp>(child[0])).toEqual(myApp);
|
||||
|
@ -161,30 +161,30 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('getViewComponent', () => {
|
||||
describe('getOwningComponent', () => {
|
||||
it('should return null when called on root component', () => {
|
||||
expect(getViewComponent(fixture.nativeElement)).toEqual(null);
|
||||
expect(getViewComponent(myApp)).toEqual(null);
|
||||
expect(getOwningComponent(fixture.nativeElement)).toEqual(null);
|
||||
expect(getOwningComponent(myApp)).toEqual(null);
|
||||
});
|
||||
it('should return containing component of child component', () => {
|
||||
expect(getViewComponent<MyApp>(child[0])).toEqual(myApp);
|
||||
expect(getViewComponent<MyApp>(child[1])).toEqual(myApp);
|
||||
expect(getViewComponent<MyApp>(child[2])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(child[0])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(child[1])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(child[2])).toEqual(myApp);
|
||||
|
||||
expect(getViewComponent<MyApp>(childComponent[0])).toEqual(myApp);
|
||||
expect(getViewComponent<MyApp>(childComponent[1])).toEqual(myApp);
|
||||
expect(getViewComponent<MyApp>(childComponent[2])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(childComponent[0])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(childComponent[1])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(childComponent[2])).toEqual(myApp);
|
||||
});
|
||||
it('should return containing component of any view element', () => {
|
||||
expect(getViewComponent<MyApp>(span[0])).toEqual(myApp);
|
||||
expect(getViewComponent<MyApp>(div[0])).toEqual(myApp);
|
||||
expect(getViewComponent<Child>(p[0])).toEqual(childComponent[0]);
|
||||
expect(getViewComponent<Child>(p[1])).toEqual(childComponent[1]);
|
||||
expect(getViewComponent<Child>(p[2])).toEqual(childComponent[2]);
|
||||
expect(getOwningComponent<MyApp>(span[0])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(div[0])).toEqual(myApp);
|
||||
expect(getOwningComponent<Child>(p[0])).toEqual(childComponent[0]);
|
||||
expect(getOwningComponent<Child>(p[1])).toEqual(childComponent[1]);
|
||||
expect(getOwningComponent<Child>(p[2])).toEqual(childComponent[2]);
|
||||
});
|
||||
it('should return containing component of child directive', () => {
|
||||
expect(getViewComponent<MyApp>(dirA[0])).toEqual(myApp);
|
||||
expect(getViewComponent<MyApp>(dirA[1])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(dirA[0])).toEqual(myApp);
|
||||
expect(getOwningComponent<MyApp>(dirA[1])).toEqual(myApp);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -231,6 +231,7 @@ onlyInIvy('Ivy-specific utilities').describe('discovery utils', () => {
|
|||
expect(listeners[0].name).toEqual('click');
|
||||
expect(listeners[0].element).toEqual(span[0]);
|
||||
expect(listeners[0].useCapture).toEqual(false);
|
||||
expect(listeners[0].type).toEqual('dom');
|
||||
listeners[0].callback('CLICKED');
|
||||
expect(log).toEqual(['CLICKED']);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
*/
|
||||
import {ɵmarkDirty as markDirty} from '@angular/core';
|
||||
|
||||
import {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getRootComponents, getViewComponent} from '../../src/render3/util/discovery_utils';
|
||||
import {applyChanges} from '../../src/render3/util/change_detection_utils';
|
||||
import {getComponent, getContext, getDirectives, getHostElement, getInjector, getListeners, getOwningComponent, getRootComponents} from '../../src/render3/util/discovery_utils';
|
||||
import {GLOBAL_PUBLISH_EXPANDO_KEY, GlobalDevModeContainer, publishDefaultGlobalUtils, publishGlobalUtil} from '../../src/render3/util/global_utils';
|
||||
import {global} from '../../src/util/global';
|
||||
|
||||
|
@ -31,8 +32,8 @@ describe('global utils', () => {
|
|||
|
||||
it('should publish getListeners', () => { assertPublished('getListeners', getListeners); });
|
||||
|
||||
it('should publish getViewComponent',
|
||||
() => { assertPublished('getViewComponent', getViewComponent); });
|
||||
it('should publish getOwningComponent',
|
||||
() => { assertPublished('getOwningComponent', getOwningComponent); });
|
||||
|
||||
it('should publish getRootComponents',
|
||||
() => { assertPublished('getRootComponents', getRootComponents); });
|
||||
|
@ -45,6 +46,8 @@ describe('global utils', () => {
|
|||
it('should publish getInjector', () => { assertPublished('getInjector', getInjector); });
|
||||
|
||||
it('should publish markDirty', () => { assertPublished('markDirty', markDirty); });
|
||||
|
||||
it('should publish applyChanges', () => { assertPublished('applyChanges', applyChanges); });
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,19 +1,27 @@
|
|||
export declare function getComponent<T = {}>(element: Element): T | null;
|
||||
export declare function applyChanges(component: {}): void;
|
||||
|
||||
export declare function getContext<T = {}>(element: Element): T | null;
|
||||
export declare function getComponent<T>(element: Element): T | null;
|
||||
|
||||
export declare function getDebugNode(element: Node): DebugNode | null;
|
||||
export declare function getContext<T>(element: Element): T | null;
|
||||
|
||||
export declare function getDirectives(target: {}): Array<{}>;
|
||||
export declare function getDirectives(element: Element): {}[];
|
||||
|
||||
export declare function getHostElement<T>(directive: T): Element;
|
||||
export declare function getHostElement(componentOrDirective: {}): Element;
|
||||
|
||||
export declare function getInjector(target: {}): Injector;
|
||||
export declare function getInjector(elementOrDir: Element | {}): Injector;
|
||||
|
||||
export declare function getListeners(element: Element): Listener[];
|
||||
|
||||
export declare function getRootComponents(target: {}): any[];
|
||||
export declare function getOwningComponent<T>(elementOrDir: Element | {}): T | null;
|
||||
|
||||
export declare function getViewComponent<T = {}>(element: Element | {}): T | null;
|
||||
export declare function getRootComponents(elementOrDir: Element | {}): {}[];
|
||||
|
||||
export declare function markDirty<T>(component: T): void;
|
||||
export interface Listener {
|
||||
callback: (value: any) => any;
|
||||
element: Element;
|
||||
name: string;
|
||||
type: 'dom' | 'output';
|
||||
useCapture: boolean;
|
||||
}
|
||||
|
||||
export declare function markDirty(component: {}): void;
|
||||
|
|
Loading…
Reference in New Issue