docs(core): add missing docs to component and fix formatting (#20855)

PR Close #20855
This commit is contained in:
Kara Erickson 2017-12-14 18:05:41 -08:00 committed by Igor Minar
parent 764fea1344
commit 5df343169e
7 changed files with 112 additions and 73 deletions

View File

@ -6,7 +6,9 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {ComponentRef, EmbeddedViewRef, Injector} from '../core'; // We are temporarily importing the existing viewEngine from core so we can be sure we are
// correctly implementing its interfaces for backwards compatibility.
import * as viewEngine from '../core';
import {assertNotNull} from './assert'; import {assertNotNull} from './assert';
import {NG_HOST_SYMBOL, createError, createViewState, directive, enterView, hostElement, leaveView, locateHostElement, renderComponentOrTemplate} from './instructions'; import {NG_HOST_SYMBOL, createError, createViewState, directive, enterView, hostElement, leaveView, locateHostElement, renderComponentOrTemplate} from './instructions';
@ -17,44 +19,41 @@ import {notImplemented, stringify} from './util';
/** /** Options that control how the component should be bootstrapped. */
* Options which control how the component should be bootstrapped. export interface CreateComponentOptions {
*/ /** Which renderer factory to use. */
export interface CreateComponentOptionArgs {
/**
* Which renderer factory to use.
*/
rendererFactory?: RendererFactory3; rendererFactory?: RendererFactory3;
/** /**
* Which host element should the component be bootstrapped on. If not specified * Host element on which the component will be bootstrapped. If not specified,
* the component definition's `tag` is used to query the existing DOM for the * the component definition's `tag` is used to query the existing DOM for the
* element to bootstrap. * element to bootstrap.
*/ */
host?: RElement|string; host?: RElement|string;
/** /** Module injector for the component. If unspecified, the injector will be NULL_INJECTOR. */
* Optional Injector which is the Module Injector for the component. injector?: viewEngine.Injector;
*/
injector?: Injector;
/** /**
* a set of features which should be applied to this component. * List of features to be applied to the created component. Features are simply
* functions that decorate a component with a certain behavior.
*
* Example: PublicFeature is a function that makes the component public to the DI system.
*/ */
features?: (<T>(component: T, componentDef: ComponentDef<T>) => void)[]; features?: (<T>(component: T, componentDef: ComponentDef<T>) => void)[];
} }
/** /**
* Bootstrap a Component into an existing host element and return `ComponentRef`. * Bootstraps a component, then creates and returns a `ComponentRef` for that component.
* *
* @param componentType Component to bootstrap * @param componentType Component to bootstrap
* @param options Optional parameters which control bootstrapping * @param options Optional parameters which control bootstrapping
*/ */
export function createComponentRef<T>( export function createComponentRef<T>(
componentType: ComponentType<T>, opts: CreateComponentOptionArgs): ComponentRef<T> { componentType: ComponentType<T>, opts: CreateComponentOptions): viewEngine.ComponentRef<T> {
const component = renderComponent(componentType, opts); const component = renderComponent(componentType, opts);
const hostView = createViewRef(detectChanges.bind(component), component); const hostView = createViewRef(() => detectChanges(component), component);
return { return {
location: {nativeElement: getHostElement(component)}, location: {nativeElement: getHostElement(component)},
injector: opts.injector || NULL_INJECTOR, injector: opts.injector || NULL_INJECTOR,
@ -62,49 +61,78 @@ export function createComponentRef<T>(
hostView: hostView, hostView: hostView,
changeDetectorRef: hostView, changeDetectorRef: hostView,
componentType: componentType, componentType: componentType,
destroy: function() {}, // TODO: implement destroy and onDestroy
onDestroy: function(cb: Function): void {} destroy: () => {},
onDestroy: (cb: Function) => {}
}; };
} }
/**
* Creates an EmbeddedViewRef.
*
* @param detectChanges The detectChanges function for this view
* @param context The context for this view
* @returns The EmbeddedViewRef
*/
function createViewRef<T>(detectChanges: () => void, context: T): EmbeddedViewRef<T> { function createViewRef<T>(detectChanges: () => void, context: T): EmbeddedViewRef<T> {
return addDestroyable( return addDestroyable(new EmbeddedViewRef(detectChanges), context);
{
// TODO: rootNodes should be replaced when properly implemented
rootNodes: null !,
// inherited from core/ChangeDetectorRef
markForCheck: () => {
if (ngDevMode) {
throw notImplemented();
}
},
detach: () => {
if (ngDevMode) {
throw notImplemented();
}
},
detectChanges: detectChanges,
checkNoChanges: () => {
if (ngDevMode) {
throw notImplemented();
}
},
reattach: () => {
if (ngDevMode) {
throw notImplemented();
}
},
},
context);
} }
interface DestroyRef<T> { class EmbeddedViewRef<T> implements viewEngine.EmbeddedViewRef<T> {
// TODO: rootNodes should be replaced when properly implemented
rootNodes = null !;
context: T; context: T;
destroyed: boolean; destroyed: boolean;
constructor(public detectChanges: () => void) {}
// inherited from core/ChangeDetectorRef
markForCheck() {
if (ngDevMode) {
throw notImplemented();
}
}
detach() {
if (ngDevMode) {
throw notImplemented();
}
}
checkNoChanges() {
if (ngDevMode) {
throw notImplemented();
}
}
reattach() {
if (ngDevMode) {
throw notImplemented();
}
}
destroy(): void {}
onDestroy(cb: Function): void {}
}
/** Interface for destroy logic. Implemented by addDestroyable. */
interface DestroyRef<T> {
context: T;
/** Whether or not this object has been destroyed */
destroyed: boolean;
/** Destroy the instance and call all onDestroy callbacks. */
destroy(): void; destroy(): void;
/** Register callbacks that should be called onDestroy */
onDestroy(cb: Function): void; onDestroy(cb: Function): void;
} }
/**
* Decorates an object with destroy logic (implementing the DestroyRef interface)
* and returns the enhanced object.
*
* @param obj The object to decorate
* @returns The object with destroy logic
*/
function addDestroyable<T, C>(obj: any, context: C): T&DestroyRef<C> { function addDestroyable<T, C>(obj: any, context: C): T&DestroyRef<C> {
let destroyFn: Function[]|null = null; let destroyFn: Function[]|null = null;
obj.destroyed = false; obj.destroyed = false;
@ -113,29 +141,28 @@ function addDestroyable<T, C>(obj: any, context: C): T&DestroyRef<C> {
this.destroyed = true; this.destroyed = true;
}; };
obj.onDestroy = (fn: Function) => (destroyFn || (destroyFn = [])).push(fn); obj.onDestroy = (fn: Function) => (destroyFn || (destroyFn = [])).push(fn);
obj.context = context;
return obj; return obj;
} }
// TODO: A hack to not pull in the NullInjector from @angular/core. // TODO: A hack to not pull in the NullInjector from @angular/core.
export const NULL_INJECTOR: Injector = { export const NULL_INJECTOR: viewEngine.Injector = {
get: function(token: any, notFoundValue?: any) { get: (token: any, notFoundValue?: any) => {
throw new Error('NullInjector: Not found: ' + stringify(token)); throw new Error('NullInjector: Not found: ' + stringify(token));
} }
}; };
/** /**
* Bootstrap a Component into an existing host element and return `NgComponent`. * Bootstraps a Component into an existing host element and returns an instance
* * of the component.
* NgComponent is a light weight Custom Elements inspired API for bootstrapping and
* interacting with bootstrapped component.
* *
* @param componentType Component to bootstrap * @param componentType Component to bootstrap
* @param options Optional parameters which control bootstrapping * @param options Optional parameters which control bootstrapping
*/ */
export function renderComponent<T>( export function renderComponent<T>(
componentType: ComponentType<T>, opts: CreateComponentOptionArgs = {}): T { componentType: ComponentType<T>, opts: CreateComponentOptions = {}): T {
const rendererFactory = opts.rendererFactory || domRendererFactory3; const rendererFactory = opts.rendererFactory || domRendererFactory3;
const componentDef = componentType.ngComponentDef; const componentDef = componentType.ngComponentDef;
let component: T; let component: T;
@ -174,7 +201,7 @@ export function markDirty<T>(
ngDevMode && assertNotNull(component, 'component'); ngDevMode && assertNotNull(component, 'component');
if (!isDirty) { if (!isDirty) {
isDirty = true; isDirty = true;
scheduler(detectChanges.bind(null, component)); scheduler(() => detectChanges(component));
} }
} }

View File

@ -13,10 +13,6 @@ import {LNodeStatic} from './l_node_static';
import {ComponentTemplate, DirectiveDef} from './public_interfaces'; import {ComponentTemplate, DirectiveDef} from './public_interfaces';
import {Renderer3} from './renderer'; import {Renderer3} from './renderer';
declare global {
const ngDevMode: boolean;
}
/** /**
* `ViewState` stores all of the information needed to process the instructions as * `ViewState` stores all of the information needed to process the instructions as
* they are invoked from the template. Each embedded view and component view has its * they are invoked from the template. Each embedded view and component view has its

View File

@ -12,13 +12,15 @@ import {DirectiveDef} from './public_interfaces';
export type NgStaticData = (LNodeStatic | DirectiveDef<any>| null)[]; export type NgStaticData = (LNodeStatic | DirectiveDef<any>| null)[];
/** /**
* LNode binding data (flywiehgt) for a particular node that is shared between all templates * LNode binding data (flyweight) for a particular node that is shared between all templates
* of a specific type. * of a specific type.
* *
* If a property is: * If a property is:
* - Minification Data: that property's data was generated and this is it * - PropertyAliases: that property's data was generated and this is it
* - Null: that property's data was already generated and nothing was found. * - Null: that property's data was already generated and nothing was found.
* - Undefined: that property's data has not yet been generated * - Undefined: that property's data has not yet been generated
*
* see: https://en.wikipedia.org/wiki/Flyweight_pattern for more on the Flyweight pattern
*/ */
export interface LNodeStatic { export interface LNodeStatic {
/** The tag name associated with this node. */ /** The tag name associated with this node. */

View File

@ -6,6 +6,11 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
declare global {
const ngDevMode: boolean;
}
if (typeof ngDevMode == 'undefined') { if (typeof ngDevMode == 'undefined') {
if (typeof window != 'undefined') (window as any).ngDevMode = true; if (typeof window != 'undefined') (window as any).ngDevMode = true;
if (typeof self != 'undefined') (self as any).ngDevMode = true; if (typeof self != 'undefined') (self as any).ngDevMode = true;

View File

@ -6,6 +6,8 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
// We are temporarily importing the existing viewEngine from core so we can be sure we are
// correctly implementing its interfaces for backwards compatibility.
import {Observable} from 'rxjs/Observable'; import {Observable} from 'rxjs/Observable';
import * as viewEngine from '../core'; import * as viewEngine from '../core';

View File

@ -26,7 +26,13 @@ export enum RendererStyleFlags3 {
export type Renderer3 = ObjectOrientedRenderer3 | ProceduralRenderer3; export type Renderer3 = ObjectOrientedRenderer3 | ProceduralRenderer3;
/** Object Oriented style of API needed to create elements and text nodes. */ /**
* Object Oriented style of API needed to create elements and text nodes.
*
* This is the native browser API style, e.g. operations are methods on individual objects
* like HTMLElement. With this style, no additional code is needed as a facade
* (reducing payload size).
* */
export interface ObjectOrientedRenderer3 { export interface ObjectOrientedRenderer3 {
createComment(data: string): RComment; createComment(data: string): RComment;
createElement(tagName: string): RElement; createElement(tagName: string): RElement;
@ -35,7 +41,13 @@ export interface ObjectOrientedRenderer3 {
querySelector(selectors: string): RElement|null; querySelector(selectors: string): RElement|null;
} }
/** Procedural style of API needed to create elements and text nodes. */ /**
* Procedural style of API needed to create elements and text nodes.
*
* In non-native browser environments (e.g. platforms such as web-workers), this is the
* facade that enables element manipulation. This also facilitates backwards compatibility
* with Renderer2.
*/
export interface ProceduralRenderer3 { export interface ProceduralRenderer3 {
destroy(): void; destroy(): void;
createElement(name: string, namespace?: string|null): RElement; createElement(name: string, namespace?: string|null): RElement;
@ -102,8 +114,8 @@ export interface RNode {
* listeners on Element. * listeners on Element.
*/ */
export interface RElement extends RNode { export interface RElement extends RNode {
style: RCSSStyleDeclaration; style: RCssStyleDeclaration;
classList: RDOMTokenList; classList: RDomTokenList;
setAttribute(name: string, value: string): void; setAttribute(name: string, value: string): void;
removeAttribute(name: string): void; removeAttribute(name: string): void;
setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void; setAttributeNS(namespaceURI: string, qualifiedName: string, value: string): void;
@ -113,12 +125,12 @@ export interface RElement extends RNode {
setProperty?(name: string, value: any): void; setProperty?(name: string, value: any): void;
} }
export interface RCSSStyleDeclaration { export interface RCssStyleDeclaration {
removeProperty(propertyName: string): string; removeProperty(propertyName: string): string;
setProperty(propertyName: string, value: string|null, priority?: string): void; setProperty(propertyName: string, value: string|null, priority?: string): void;
} }
export interface RDOMTokenList { export interface RDomTokenList {
add(token: string): void; add(token: string): void;
remove(token: string): void; remove(token: string): void;
} }

View File

@ -34,11 +34,6 @@ describe('component', () => {
}); });
} }
beforeEach(
() => {
});
describe('renderComponent', () => { describe('renderComponent', () => {
it('should render on initial call', () => { it('should render on initial call', () => {
renderComponent(CounterComponent); renderComponent(CounterComponent);