feat(core): added afterContentInit, afterViewInit, and afterViewChecked hooks

Closes #3897
This commit is contained in:
vsavkin 2015-08-28 18:11:04 -07:00 committed by Victor Savkin
parent f93cd9ced7
commit d49bc438e8
36 changed files with 974 additions and 253 deletions

View File

@ -38,7 +38,10 @@ export {
} from './src/core/metadata'; } from './src/core/metadata';
export { export {
AfterContentInit,
AfterContentChecked, AfterContentChecked,
AfterViewInit,
AfterViewChecked,
OnChanges, OnChanges,
OnDestroy, OnDestroy,
OnInit, OnInit,

View File

@ -82,12 +82,19 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
this.mode === ChangeDetectionStrategy.Checked) this.mode === ChangeDetectionStrategy.Checked)
return; return;
var s = _scope_check(this.id, throwOnChange); var s = _scope_check(this.id, throwOnChange);
this.detectChangesInRecords(throwOnChange); this.detectChangesInRecords(throwOnChange);
this._detectChangesInLightDomChildren(throwOnChange); this._detectChangesInLightDomChildren(throwOnChange);
if (throwOnChange === false) this.callAfterContentChecked(); if (!throwOnChange) this.afterContentLifecycleCallbacks();
this._detectChangesInShadowDomChildren(throwOnChange); this._detectChangesInShadowDomChildren(throwOnChange);
if (!throwOnChange) this.afterViewLifecycleCallbacks();
if (this.mode === ChangeDetectionStrategy.CheckOnce) if (this.mode === ChangeDetectionStrategy.CheckOnce)
this.mode = ChangeDetectionStrategy.Checked; this.mode = ChangeDetectionStrategy.Checked;
this.alreadyChecked = true;
wtfLeave(s); wtfLeave(s);
} }
@ -156,7 +163,19 @@ export class AbstractChangeDetector<T> implements ChangeDetector {
hydrated(): boolean { return this.context !== null; } hydrated(): boolean { return this.context !== null; }
callAfterContentChecked(): void { this.dispatcher.notifyAfterContentChecked(); } afterContentLifecycleCallbacks(): void {
this.dispatcher.notifyAfterContentChecked();
this.afterContentLifecycleCallbacksInternal();
}
afterContentLifecycleCallbacksInternal(): void {}
afterViewLifecycleCallbacks(): void {
this.dispatcher.notifyAfterViewChecked();
this.afterViewLifecycleCallbacksInternal();
}
afterViewLifecycleCallbacksInternal(): void {}
_detectChangesInLightDomChildren(throwOnChange: boolean): void { _detectChangesInLightDomChildren(throwOnChange: boolean): void {
var c = this.lightDomChildren; var c = this.lightDomChildren;

View File

@ -63,23 +63,23 @@ export class ChangeDetectorJITGenerator {
var ${CHANGES_LOCAL} = null; var ${CHANGES_LOCAL} = null;
${this.records.map((r) => this._genRecord(r)).join("\n")} ${this.records.map((r) => this._genRecord(r)).join("\n")}
${this._names.getAlreadyCheckedName()} = true;
} }
${this._maybeGenHandleEventInternal()} ${this._maybeGenHandleEventInternal()}
${this._genCheckNoChanges()} ${this._genCheckNoChanges()}
${this._maybeGenCallAfterContentChecked()} ${this._maybeGenAfterContentLifecycleCallbacks()}
${this._maybeGenAfterViewLifecycleCallbacks()}
${this._maybeGenHydrateDirectives()} ${this._maybeGenHydrateDirectives()}
${this._maybeGenDehydrateDirectives()} ${this._maybeGenDehydrateDirectives()}
${this._genPropertyBindingTargets()}; ${this._genPropertyBindingTargets()}
${this._genDirectiveIndices()}; ${this._genDirectiveIndices()}
return function(dispatcher) { return function(dispatcher) {
return new ${this._typeName}(dispatcher); return new ${this._typeName}(dispatcher);
@ -172,23 +172,26 @@ export class ChangeDetectorJITGenerator {
}`; }`;
} }
_maybeGenCallAfterContentChecked(): string { _maybeGenAfterContentLifecycleCallbacks(): string {
var notifications = []; var notifications = this._logic.genContentLifecycleCallbacks(this.directiveRecords);
var dirs = this.directiveRecords;
// NOTE(kegluneq): Order is important!
for (var i = dirs.length - 1; i >= 0; --i) {
var dir = dirs[i];
if (dir.callAfterContentChecked) {
notifications.push(
`${this._names.getDirectiveName(dir.directiveIndex)}.afterContentChecked();`);
}
}
if (notifications.length > 0) { if (notifications.length > 0) {
var directiveNotifications = notifications.join("\n"); var directiveNotifications = notifications.join("\n");
return ` return `
${this._typeName}.prototype.callAfterContentChecked = function() { ${this._typeName}.prototype.afterContentLifecycleCallbacksInternal = function() {
${ABSTRACT_CHANGE_DETECTOR}.prototype.callAfterContentChecked.call(this); ${directiveNotifications}
}
`;
} else {
return '';
}
}
_maybeGenAfterViewLifecycleCallbacks(): string {
var notifications = this._logic.genViewLifecycleCallbacks(this.directiveRecords);
if (notifications.length > 0) {
var directiveNotifications = notifications.join("\n");
return `
${this._typeName}.prototype.afterViewLifecycleCallbacksInternal = function() {
${directiveNotifications} ${directiveNotifications}
} }
`; `;

View File

@ -183,4 +183,38 @@ export class CodegenLogicUtil {
} }
return res.join("\n"); return res.join("\n");
} }
genContentLifecycleCallbacks(directiveRecords: DirectiveRecord[]): string[] {
var res = [];
// NOTE(kegluneq): Order is important!
for (var i = directiveRecords.length - 1; i >= 0; --i) {
var dir = directiveRecords[i];
if (dir.callAfterContentInit) {
res.push(
`if(! ${this._names.getAlreadyCheckedName()}) ${this._names.getDirectiveName(dir.directiveIndex)}.afterContentInit();`);
}
if (dir.callAfterContentChecked) {
res.push(`${this._names.getDirectiveName(dir.directiveIndex)}.afterContentChecked();`);
}
}
return res;
}
genViewLifecycleCallbacks(directiveRecords: DirectiveRecord[]): string[] {
var res = [];
// NOTE(kegluneq): Order is important!
for (var i = directiveRecords.length - 1; i >= 0; --i) {
var dir = directiveRecords[i];
if (dir.callAfterViewInit) {
res.push(
`if(! ${this._names.getAlreadyCheckedName()}) ${this._names.getDirectiveName(dir.directiveIndex)}.afterViewInit();`);
}
if (dir.callAfterViewChecked) {
res.push(`${this._names.getDirectiveName(dir.directiveIndex)}.afterViewChecked();`);
}
}
return res;
}
} }

View File

@ -9,24 +9,33 @@ export class DirectiveIndex {
export class DirectiveRecord { export class DirectiveRecord {
directiveIndex: DirectiveIndex; directiveIndex: DirectiveIndex;
callAfterContentInit: boolean;
callAfterContentChecked: boolean; callAfterContentChecked: boolean;
callAfterViewInit: boolean;
callAfterViewChecked: boolean;
callOnChanges: boolean; callOnChanges: boolean;
callDoCheck: boolean; callDoCheck: boolean;
callOnInit: boolean; callOnInit: boolean;
changeDetection: ChangeDetectionStrategy; changeDetection: ChangeDetectionStrategy;
constructor({directiveIndex, callAfterContentChecked, callOnChanges, callDoCheck, callOnInit, constructor({directiveIndex, callAfterContentInit, callAfterContentChecked, callAfterViewInit,
changeDetection}: { callAfterViewChecked, callOnChanges, callDoCheck, callOnInit, changeDetection}: {
directiveIndex?: DirectiveIndex, directiveIndex?: DirectiveIndex,
callAfterContentInit?: boolean,
callAfterContentChecked?: boolean, callAfterContentChecked?: boolean,
callAfterViewInit?: boolean,
callAfterViewChecked?: boolean,
callOnChanges?: boolean, callOnChanges?: boolean,
callDoCheck?: boolean, callDoCheck?: boolean,
callOnInit?: boolean, callOnInit?: boolean,
changeDetection?: ChangeDetectionStrategy changeDetection?: ChangeDetectionStrategy
} = {}) { } = {}) {
this.directiveIndex = directiveIndex; this.directiveIndex = directiveIndex;
this.callAfterContentInit = normalizeBool(callAfterContentInit);
this.callAfterContentChecked = normalizeBool(callAfterContentChecked); this.callAfterContentChecked = normalizeBool(callAfterContentChecked);
this.callOnChanges = normalizeBool(callOnChanges); this.callOnChanges = normalizeBool(callOnChanges);
this.callAfterViewInit = normalizeBool(callAfterViewInit);
this.callAfterViewChecked = normalizeBool(callAfterViewChecked);
this.callDoCheck = normalizeBool(callDoCheck); this.callDoCheck = normalizeBool(callDoCheck);
this.callOnInit = normalizeBool(callOnInit); this.callOnInit = normalizeBool(callOnInit);
this.changeDetection = changeDetection; this.changeDetection = changeDetection;

View File

@ -159,8 +159,6 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
isChanged = false; isChanged = false;
} }
} }
this.alreadyChecked = true;
} }
_firstInBinding(r: ProtoRecord): boolean { _firstInBinding(r: ProtoRecord): boolean {
@ -168,17 +166,33 @@ export class DynamicChangeDetector extends AbstractChangeDetector<any> {
return isBlank(prev) || prev.bindingRecord !== r.bindingRecord; return isBlank(prev) || prev.bindingRecord !== r.bindingRecord;
} }
callAfterContentChecked() { afterContentLifecycleCallbacksInternal() {
super.callAfterContentChecked();
var dirs = this.directiveRecords; var dirs = this.directiveRecords;
for (var i = dirs.length - 1; i >= 0; --i) { for (var i = dirs.length - 1; i >= 0; --i) {
var dir = dirs[i]; var dir = dirs[i];
if (dir.callAfterContentInit && !this.alreadyChecked) {
this._getDirectiveFor(dir.directiveIndex).afterContentInit();
}
if (dir.callAfterContentChecked) { if (dir.callAfterContentChecked) {
this._getDirectiveFor(dir.directiveIndex).afterContentChecked(); this._getDirectiveFor(dir.directiveIndex).afterContentChecked();
} }
} }
} }
afterViewLifecycleCallbacksInternal() {
var dirs = this.directiveRecords;
for (var i = dirs.length - 1; i >= 0; --i) {
var dir = dirs[i];
if (dir.callAfterViewInit && !this.alreadyChecked) {
this._getDirectiveFor(dir.directiveIndex).afterViewInit();
}
if (dir.callAfterViewChecked) {
this._getDirectiveFor(dir.directiveIndex).afterViewChecked();
}
}
}
_updateDirectiveOrElement(change, bindingRecord) { _updateDirectiveOrElement(change, bindingRecord) {
if (isBlank(bindingRecord.directiveRecord)) { if (isBlank(bindingRecord.directiveRecord)) {
super.notifyDispatcher(change.currentValue); super.notifyDispatcher(change.currentValue);

View File

@ -52,6 +52,7 @@ export interface ChangeDispatcher {
notifyOnBinding(bindingTarget: BindingTarget, value: any): void; notifyOnBinding(bindingTarget: BindingTarget, value: any): void;
logBindingUpdate(bindingTarget: BindingTarget, value: any): void; logBindingUpdate(bindingTarget: BindingTarget, value: any): void;
notifyAfterContentChecked(): void; notifyAfterContentChecked(): void;
notifyAfterViewChecked(): void;
} }
export interface ChangeDetector { export interface ChangeDetector {

View File

@ -17,8 +17,14 @@ bool hasLifecycleHook(LifecycleEvent e, type, DirectiveMetadata annotation) {
interface = OnChanges; interface = OnChanges;
} else if (e == LifecycleEvent.OnDestroy) { } else if (e == LifecycleEvent.OnDestroy) {
interface = OnDestroy; interface = OnDestroy;
} else if (e == LifecycleEvent.AfterContentInit) {
interface = AfterContentInit;
} else if (e == LifecycleEvent.AfterContentChecked) { } else if (e == LifecycleEvent.AfterContentChecked) {
interface = AfterContentChecked; interface = AfterContentChecked;
} else if (e == LifecycleEvent.AfterViewInit) {
interface = AfterViewInit;
} else if (e == LifecycleEvent.AfterViewChecked) {
interface = AfterViewChecked;
} else if (e == LifecycleEvent.DoCheck) { } else if (e == LifecycleEvent.DoCheck) {
interface = DoCheck; interface = DoCheck;
} else if (e == LifecycleEvent.OnInit) { } else if (e == LifecycleEvent.OnInit) {

View File

@ -8,8 +8,14 @@ export function hasLifecycleHook(e: LifecycleEvent, type, annotation: DirectiveM
if (!(type instanceof Type)) return false; if (!(type instanceof Type)) return false;
var proto = (<any>type).prototype; var proto = (<any>type).prototype;
switch (e) { switch (e) {
case LifecycleEvent.AfterContentInit:
return !!proto.afterContentInit;
case LifecycleEvent.AfterContentChecked: case LifecycleEvent.AfterContentChecked:
return !!proto.afterContentChecked; return !!proto.afterContentChecked;
case LifecycleEvent.AfterViewInit:
return !!proto.afterViewInit;
case LifecycleEvent.AfterViewChecked:
return !!proto.afterViewChecked;
case LifecycleEvent.OnChanges: case LifecycleEvent.OnChanges:
return !!proto.onChanges; return !!proto.onChanges;
case LifecycleEvent.DoCheck: case LifecycleEvent.DoCheck:

View File

@ -216,38 +216,41 @@ export class DirectiveBinding extends ResolvedBinding {
get changeDetection() { return this.metadata.changeDetection; } get changeDetection() { return this.metadata.changeDetection; }
static createFromBinding(binding: Binding, ann: DirectiveMetadata): DirectiveBinding { static createFromBinding(binding: Binding, meta: DirectiveMetadata): DirectiveBinding {
if (isBlank(ann)) { if (isBlank(meta)) {
ann = new DirectiveMetadata(); meta = new DirectiveMetadata();
} }
var rb = binding.resolve(); var rb = binding.resolve();
var deps = ListWrapper.map(rb.dependencies, DirectiveDependency.createFrom); var deps = ListWrapper.map(rb.dependencies, DirectiveDependency.createFrom);
var resolvedBindings = isPresent(ann.bindings) ? Injector.resolve(ann.bindings) : []; var resolvedBindings = isPresent(meta.bindings) ? Injector.resolve(meta.bindings) : [];
var resolvedViewBindings = ann instanceof ComponentMetadata && isPresent(ann.viewBindings) ? var resolvedViewBindings = meta instanceof ComponentMetadata && isPresent(meta.viewBindings) ?
Injector.resolve(ann.viewBindings) : Injector.resolve(meta.viewBindings) :
[]; [];
var metadata = RenderDirectiveMetadata.create({ var metadata = RenderDirectiveMetadata.create({
id: stringify(rb.key.token), id: stringify(rb.key.token),
type: ann instanceof ComponentMetadata ? RenderDirectiveMetadata.COMPONENT_TYPE : type: meta instanceof ComponentMetadata ? RenderDirectiveMetadata.COMPONENT_TYPE :
RenderDirectiveMetadata.DIRECTIVE_TYPE, RenderDirectiveMetadata.DIRECTIVE_TYPE,
selector: ann.selector, selector: meta.selector,
compileChildren: ann.compileChildren, compileChildren: meta.compileChildren,
events: ann.events, events: meta.events,
host: isPresent(ann.host) ? MapWrapper.createFromStringMap(ann.host) : null, host: isPresent(meta.host) ? MapWrapper.createFromStringMap(meta.host) : null,
properties: ann.properties, properties: meta.properties,
readAttributes: DirectiveBinding._readAttributes(deps), readAttributes: DirectiveBinding._readAttributes(deps),
callOnDestroy: hasLifecycleHook(LifecycleEvent.OnDestroy, rb.key.token, ann), callOnDestroy: hasLifecycleHook(LifecycleEvent.OnDestroy, rb.key.token, meta),
callOnChanges: hasLifecycleHook(LifecycleEvent.OnChanges, rb.key.token, ann), callOnChanges: hasLifecycleHook(LifecycleEvent.OnChanges, rb.key.token, meta),
callDoCheck: hasLifecycleHook(LifecycleEvent.DoCheck, rb.key.token, ann), callDoCheck: hasLifecycleHook(LifecycleEvent.DoCheck, rb.key.token, meta),
callOnInit: hasLifecycleHook(LifecycleEvent.OnInit, rb.key.token, ann), callOnInit: hasLifecycleHook(LifecycleEvent.OnInit, rb.key.token, meta),
callAfterContentInit: hasLifecycleHook(LifecycleEvent.AfterContentInit, rb.key.token, meta),
callAfterContentChecked: callAfterContentChecked:
hasLifecycleHook(LifecycleEvent.AfterContentChecked, rb.key.token, ann), hasLifecycleHook(LifecycleEvent.AfterContentChecked, rb.key.token, meta),
callAfterViewInit: hasLifecycleHook(LifecycleEvent.AfterViewInit, rb.key.token, meta),
callAfterViewChecked: hasLifecycleHook(LifecycleEvent.AfterViewChecked, rb.key.token, meta),
changeDetection: ann instanceof ComponentMetadata ? ann.changeDetection : null, changeDetection: meta instanceof ComponentMetadata ? meta.changeDetection : null,
exportAs: ann.exportAs exportAs: meta.exportAs
}); });
return new DirectiveBinding(rb.key, rb.factory, deps, resolvedBindings, resolvedViewBindings, return new DirectiveBinding(rb.key, rb.factory, deps, resolvedBindings, resolvedViewBindings,
metadata); metadata);

View File

@ -29,9 +29,30 @@ export interface DoCheck { doCheck(): boolean; }
*/ */
export interface OnDestroy { onDestroy(): void; } export interface OnDestroy { onDestroy(): void; }
/**
* Defines lifecycle method
* {@link metadata/LifeCycleEvent#AfterContentInit `LifeCycleEvent.afterContentInit`}
* called when the bindings of all its content children have been checked the first time.
*/
export interface AfterContentInit { afterContentInit(): void; }
/** /**
* Defines lifecycle method * Defines lifecycle method
* {@link metadata/LifeCycleEvent#AfterContentChecked `LifeCycleEvent.afterContentChecked`} * {@link metadata/LifeCycleEvent#AfterContentChecked `LifeCycleEvent.afterContentChecked`}
* called when the bindings of all its view children have been changed. * called when the bindings of all its content children have been checked.
*/ */
export interface AfterContentChecked { afterContentChecked(): void; } export interface AfterContentChecked { afterContentChecked(): void; }
/**
* Defines lifecycle method
* {@link metadata/LifeCycleEvent#AfterViewInit `LifeCycleEvent.afterViewInit`}
* called when the bindings of all its view children have been checked the first time.
*/
export interface AfterViewInit { afterViewInit(): void; }
/**
* Defines lifecycle method
* {@link metadata/LifeCycleEvent#AfterViewChecked `LifeCycleEvent.afterViewChecked`}
* called when the bindings of all its view children have been checked.
*/
export interface AfterViewChecked { afterViewChecked(): void; }

View File

@ -191,7 +191,10 @@ export class BindingRecordsCreator {
this._directiveRecordsMap.set( this._directiveRecordsMap.set(
id, new DirectiveRecord({ id, new DirectiveRecord({
directiveIndex: new DirectiveIndex(boundElementIndex, directiveIndex), directiveIndex: new DirectiveIndex(boundElementIndex, directiveIndex),
callAfterContentInit: directiveMetadata.callAfterContentInit,
callAfterContentChecked: directiveMetadata.callAfterContentChecked, callAfterContentChecked: directiveMetadata.callAfterContentChecked,
callAfterViewInit: directiveMetadata.callAfterViewInit,
callAfterViewChecked: directiveMetadata.callAfterViewChecked,
callOnChanges: directiveMetadata.callOnChanges, callOnChanges: directiveMetadata.callOnChanges,
callDoCheck: directiveMetadata.callDoCheck, callDoCheck: directiveMetadata.callDoCheck,
callOnInit: directiveMetadata.callOnInit, callOnInit: directiveMetadata.callOnInit,

View File

@ -212,6 +212,10 @@ export class AppView implements ChangeDispatcher, RenderEventDispatcher {
} }
} }
notifyAfterViewChecked(): void {
// required for query
}
getDirectiveFor(directive: DirectiveIndex): any { getDirectiveFor(directive: DirectiveIndex): any {
var elementInjector = this.elementInjectors[this.elementOffset + directive.elementIndex]; var elementInjector = this.elementInjectors[this.elementOffset + directive.elementIndex];
return elementInjector.getDirectiveAtIndex(directive.directiveIndex); return elementInjector.getDirectiveAtIndex(directive.directiveIndex);

View File

@ -961,7 +961,30 @@ export enum LifecycleEvent {
DoCheck, DoCheck,
/** /**
* Notify a directive when the bindings of all its view children have been checked (whether they * Notify a directive when the bindings of all its content children have been checked the first
* time (whether they
* have changed or not).
*
* ## Example
*
* ```
* @Directive({
* selector: '[class-set]',
* lifecycle: [LifecycleEvent.AfterContentInit]
* })
* class ClassSet {
*
* afterContentInit() {
* }
*
* }
* ```
*/
AfterContentInit,
/**
* Notify a directive when the bindings of all its content children have been checked (whether
* they
* have changed or not). * have changed or not).
* *
* ## Example * ## Example
@ -979,7 +1002,50 @@ export enum LifecycleEvent {
* } * }
* ``` * ```
*/ */
AfterContentChecked AfterContentChecked,
/**
* Notify a directive when the bindings of all its view children have been checked the first time
* (whether they
* have changed or not).
*
* ## Example
*
* ```
* @Directive({
* selector: '[class-set]',
* lifecycle: [LifecycleEvent.AfterViewInit]
* })
* class ClassSet {
*
* afterViewInit() {
* }
*
* }
* ```
*/
AfterViewInit,
/**
* Notify a directive when the bindings of all its view children have been checked (whether they
* have changed or not).
*
* ## Example
*
* ```
* @Directive({
* selector: '[class-set]',
* lifecycle: [LifecycleEvent.AfterViewChecked]
* })
* class ClassSet {
*
* afterViewChecked() {
* }
*
* }
* ```
*/
AfterViewChecked
} }
/** /**

View File

@ -157,7 +157,10 @@ export class RenderDirectiveMetadata {
callOnChanges: boolean; callOnChanges: boolean;
callDoCheck: boolean; callDoCheck: boolean;
callOnInit: boolean; callOnInit: boolean;
callAfterContentInit: boolean;
callAfterContentChecked: boolean; callAfterContentChecked: boolean;
callAfterViewInit: boolean;
callAfterViewChecked: boolean;
changeDetection: ChangeDetectionStrategy; changeDetection: ChangeDetectionStrategy;
exportAs: string; exportAs: string;
hostListeners: Map<string, string>; hostListeners: Map<string, string>;
@ -169,7 +172,8 @@ export class RenderDirectiveMetadata {
constructor({id, selector, compileChildren, events, hostListeners, hostProperties, hostAttributes, constructor({id, selector, compileChildren, events, hostListeners, hostProperties, hostAttributes,
properties, readAttributes, type, callOnDestroy, callOnChanges, callDoCheck, properties, readAttributes, type, callOnDestroy, callOnChanges, callDoCheck,
callOnInit, callAfterContentChecked, changeDetection, exportAs}: { callOnInit, callAfterContentInit, callAfterContentChecked, callAfterViewInit,
callAfterViewChecked, changeDetection, exportAs}: {
id?: string, id?: string,
selector?: string, selector?: string,
compileChildren?: boolean, compileChildren?: boolean,
@ -184,7 +188,10 @@ export class RenderDirectiveMetadata {
callOnChanges?: boolean, callOnChanges?: boolean,
callDoCheck?: boolean, callDoCheck?: boolean,
callOnInit?: boolean, callOnInit?: boolean,
callAfterContentInit?: boolean,
callAfterContentChecked?: boolean, callAfterContentChecked?: boolean,
callAfterViewInit?: boolean,
callAfterViewChecked?: boolean,
changeDetection?: ChangeDetectionStrategy, changeDetection?: ChangeDetectionStrategy,
exportAs?: string exportAs?: string
}) { }) {
@ -202,14 +209,18 @@ export class RenderDirectiveMetadata {
this.callOnChanges = callOnChanges; this.callOnChanges = callOnChanges;
this.callDoCheck = callDoCheck; this.callDoCheck = callDoCheck;
this.callOnInit = callOnInit; this.callOnInit = callOnInit;
this.callAfterContentInit = callAfterContentInit;
this.callAfterContentChecked = callAfterContentChecked; this.callAfterContentChecked = callAfterContentChecked;
this.callAfterViewInit = callAfterViewInit;
this.callAfterViewChecked = callAfterViewChecked;
this.changeDetection = changeDetection; this.changeDetection = changeDetection;
this.exportAs = exportAs; this.exportAs = exportAs;
} }
static create({id, selector, compileChildren, events, host, properties, readAttributes, type, static create({id, selector, compileChildren, events, host, properties, readAttributes, type,
callOnDestroy, callOnChanges, callDoCheck, callOnInit, callAfterContentChecked, callOnDestroy, callOnChanges, callDoCheck, callOnInit, callAfterContentInit,
changeDetection, exportAs}: { callAfterContentChecked, callAfterViewInit, callAfterViewChecked, changeDetection,
exportAs}: {
id?: string, id?: string,
selector?: string, selector?: string,
compileChildren?: boolean, compileChildren?: boolean,
@ -222,7 +233,10 @@ export class RenderDirectiveMetadata {
callOnChanges?: boolean, callOnChanges?: boolean,
callDoCheck?: boolean, callDoCheck?: boolean,
callOnInit?: boolean, callOnInit?: boolean,
callAfterContentInit?: boolean,
callAfterContentChecked?: boolean, callAfterContentChecked?: boolean,
callAfterViewInit?: boolean,
callAfterViewChecked?: boolean,
changeDetection?: ChangeDetectionStrategy, changeDetection?: ChangeDetectionStrategy,
exportAs?: string exportAs?: string
}): RenderDirectiveMetadata { }): RenderDirectiveMetadata {
@ -258,7 +272,10 @@ export class RenderDirectiveMetadata {
callOnChanges: callOnChanges, callOnChanges: callOnChanges,
callDoCheck: callDoCheck, callDoCheck: callDoCheck,
callOnInit: callOnInit, callOnInit: callOnInit,
callAfterContentInit: callAfterContentInit,
callAfterContentChecked: callAfterContentChecked, callAfterContentChecked: callAfterContentChecked,
callAfterViewInit: callAfterViewInit,
callAfterViewChecked: callAfterViewChecked,
changeDetection: changeDetection, changeDetection: changeDetection,
exportAs: exportAs exportAs: exportAs
}); });

View File

@ -19,6 +19,8 @@ export class Log {
return (a1 = null, a2 = null, a3 = null, a4 = null, a5 = null) => { this._result.push(value); } return (a1 = null, a2 = null, a3 = null, a4 = null, a5 = null) => { this._result.push(value); }
} }
clear(): void { this._result = []; }
result(): string { return ListWrapper.join(this._result, "; "); } result(): string { return ListWrapper.join(this._result, "; "); }
} }

View File

@ -284,13 +284,21 @@ class _DirectiveUpdating {
directiveIndex: new DirectiveIndex(0, 0), directiveIndex: new DirectiveIndex(0, 0),
callOnChanges: true, callOnChanges: true,
callDoCheck: true, callDoCheck: true,
callAfterContentChecked: true callOnInit: true,
callAfterContentInit: true,
callAfterContentChecked: true,
callAfterViewInit: true,
callAfterViewChecked: true
}), }),
new DirectiveRecord({ new DirectiveRecord({
directiveIndex: new DirectiveIndex(0, 1), directiveIndex: new DirectiveIndex(0, 1),
callOnChanges: true, callOnChanges: true,
callDoCheck: true, callDoCheck: true,
callAfterContentChecked: true callOnInit: true,
callAfterContentInit: true,
callAfterContentChecked: true,
callAfterViewInit: true,
callAfterViewChecked: true
}) })
]; ];
@ -298,7 +306,11 @@ class _DirectiveUpdating {
directiveIndex: new DirectiveIndex(0, 0), directiveIndex: new DirectiveIndex(0, 0),
callOnChanges: false, callOnChanges: false,
callDoCheck: false, callDoCheck: false,
callAfterContentChecked: false callOnInit: false,
callAfterContentInit: false,
callAfterContentChecked: false,
callAfterViewInit: false,
callAfterViewChecked: false
}); });
/** /**

View File

@ -1,4 +1,3 @@
///<reference path="../../../src/core/change_detection/pipe_transform.ts"/>
import { import {
ddescribe, ddescribe,
describe, describe,
@ -361,12 +360,18 @@ export function main() {
}); });
}); });
it('should notify the dispatcher on all changes done', () => { it('should notify the dispatcher after content children have checked', () => {
var val = _createChangeDetector('name', new Person('bob')); var val = _createChangeDetector('name', new Person('bob'));
val.changeDetector.detectChanges(); val.changeDetector.detectChanges();
expect(val.dispatcher.afterContentCheckedCalled).toEqual(true); expect(val.dispatcher.afterContentCheckedCalled).toEqual(true);
}); });
it('should notify the dispatcher after view children have been checked', () => {
var val = _createChangeDetector('name', new Person('bob'));
val.changeDetector.detectChanges();
expect(val.dispatcher.afterViewCheckedCalled).toEqual(true);
});
describe('updating directives', () => { describe('updating directives', () => {
var directive1; var directive1;
var directive2; var directive2;
@ -385,6 +390,7 @@ export function main() {
expect(directive1.a).toEqual(42); expect(directive1.a).toEqual(42);
}); });
describe('lifecycle', () => {
describe('onChanges', () => { describe('onChanges', () => {
it('should notify the directive when a group of records changes', () => { it('should notify the directive when a group of records changes', () => {
var cd = _createWithoutHydrate('groupChanges').changeDetector; var cd = _createWithoutHydrate('groupChanges').changeDetector;
@ -425,7 +431,8 @@ export function main() {
it('should notify the directive after it has been checked the first time', () => { it('should notify the directive after it has been checked the first time', () => {
var cd = _createWithoutHydrate('directiveOnInit').changeDetector; var cd = _createWithoutHydrate('directiveOnInit').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null); cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1, directive2], []),
null);
cd.detectChanges(); cd.detectChanges();
@ -449,6 +456,45 @@ export function main() {
}); });
}); });
describe('afterContentInit', () => {
it('should be called after processing the content children', () => {
var cd = _createWithoutHydrate('emptyWithDirectiveRecords').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1, directive2], []),
null);
cd.detectChanges();
expect(directive1.afterContentInitCalled).toBe(true);
expect(directive2.afterContentInitCalled).toBe(true);
// reset directives
directive1.afterContentInitCalled = false;
directive2.afterContentInitCalled = false;
// Verify that checking should not call them.
cd.checkNoChanges();
expect(directive1.afterContentInitCalled).toBe(false);
expect(directive2.afterContentInitCalled).toBe(false);
// re-verify that changes should not call them
cd.detectChanges();
expect(directive1.afterContentInitCalled).toBe(false);
expect(directive2.afterContentInitCalled).toBe(false);
});
it('should not be called when afterContentInit is false', () => {
var cd = _createWithoutHydrate('noCallbacks').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null);
cd.detectChanges();
expect(directive1.afterContentInitCalled).toEqual(false);
});
});
describe('afterContentChecked', () => { describe('afterContentChecked', () => {
it('should be called after processing all the children', () => { it('should be called after processing all the children', () => {
var cd = _createWithoutHydrate('emptyWithDirectiveRecords').changeDetector; var cd = _createWithoutHydrate('emptyWithDirectiveRecords').changeDetector;
@ -477,7 +523,6 @@ export function main() {
expect(directive2.afterContentCheckedCalled).toBe(true); expect(directive2.afterContentCheckedCalled).toBe(true);
}); });
it('should not be called when afterContentChecked is false', () => { it('should not be called when afterContentChecked is false', () => {
var cd = _createWithoutHydrate('noCallbacks').changeDetector; var cd = _createWithoutHydrate('noCallbacks').changeDetector;
@ -504,29 +549,150 @@ export function main() {
expect(onChangesDoneCalls).toEqual([td2, td1]); expect(onChangesDoneCalls).toEqual([td2, td1]);
}); });
it('should be called before processing shadow dom children', () => { it('should be called before processing view children', () => {
var parent = _createWithoutHydrate('directNoDispatcher').changeDetector; var parent = _createWithoutHydrate('directNoDispatcher').changeDetector;
var child = _createWithoutHydrate('directNoDispatcher').changeDetector; var child = _createWithoutHydrate('directNoDispatcher').changeDetector;
parent.addShadowDomChild(child); parent.addShadowDomChild(child);
var orderOfOperations = []; var orderOfOperations = [];
var directiveInShadowDom = null; var directiveInShadowDom;
directiveInShadowDom = directiveInShadowDom =
new TestDirective(() => { orderOfOperations.push(directiveInShadowDom); }); new TestDirective(() => { orderOfOperations.push(directiveInShadowDom); });
var parentDirective = null; var parentDirective;
parentDirective = parentDirective =
new TestDirective(() => { orderOfOperations.push(parentDirective); }); new TestDirective(() => { orderOfOperations.push(parentDirective); });
parent.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([parentDirective], []), parent.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([parentDirective], []),
null); null);
child.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directiveInShadowDom], []), child.hydrate(_DEFAULT_CONTEXT, null,
null); new FakeDirectives([directiveInShadowDom], []), null);
parent.detectChanges(); parent.detectChanges();
expect(orderOfOperations).toEqual([parentDirective, directiveInShadowDom]); expect(orderOfOperations).toEqual([parentDirective, directiveInShadowDom]);
}); });
}); });
describe('afterViewInit', () => {
it('should be called after processing the view children', () => {
var cd = _createWithoutHydrate('emptyWithDirectiveRecords').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1, directive2], []),
null);
cd.detectChanges();
expect(directive1.afterViewInitCalled).toBe(true);
expect(directive2.afterViewInitCalled).toBe(true);
// reset directives
directive1.afterViewInitCalled = false;
directive2.afterViewInitCalled = false;
// Verify that checking should not call them.
cd.checkNoChanges();
expect(directive1.afterViewInitCalled).toBe(false);
expect(directive2.afterViewInitCalled).toBe(false);
// re-verify that changes should not call them
cd.detectChanges();
expect(directive1.afterViewInitCalled).toBe(false);
expect(directive2.afterViewInitCalled).toBe(false);
});
it('should not be called when afterViewInit is false', () => {
var cd = _createWithoutHydrate('noCallbacks').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null);
cd.detectChanges();
expect(directive1.afterViewInitCalled).toEqual(false);
});
});
describe('afterViewChecked', () => {
it('should be called after processing the view children', () => {
var cd = _createWithoutHydrate('emptyWithDirectiveRecords').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1, directive2], []),
null);
cd.detectChanges();
expect(directive1.afterViewCheckedCalled).toBe(true);
expect(directive2.afterViewCheckedCalled).toBe(true);
// reset directives
directive1.afterViewCheckedCalled = false;
directive2.afterViewCheckedCalled = false;
// Verify that checking should not call them.
cd.checkNoChanges();
expect(directive1.afterViewCheckedCalled).toBe(false);
expect(directive2.afterViewCheckedCalled).toBe(false);
// re-verify that changes should call them
cd.detectChanges();
expect(directive1.afterViewCheckedCalled).toBe(true);
expect(directive2.afterViewCheckedCalled).toBe(true);
});
it('should not be called when afterViewChecked is false', () => {
var cd = _createWithoutHydrate('noCallbacks').changeDetector;
cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([directive1], []), null);
cd.detectChanges();
expect(directive1.afterViewCheckedCalled).toEqual(false);
});
it('should be called in reverse order so the child is always notified before the parent',
() => {
var cd = _createWithoutHydrate('emptyWithDirectiveRecords').changeDetector;
var onChangesDoneCalls = [];
var td1;
td1 = new TestDirective(null, () => onChangesDoneCalls.push(td1));
var td2;
td2 = new TestDirective(null, () => onChangesDoneCalls.push(td2));
cd.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([td1, td2], []), null);
cd.detectChanges();
expect(onChangesDoneCalls).toEqual([td2, td1]);
});
it('should be called after processing view children', () => {
var parent = _createWithoutHydrate('directNoDispatcher').changeDetector;
var child = _createWithoutHydrate('directNoDispatcher').changeDetector;
parent.addShadowDomChild(child);
var orderOfOperations = [];
var directiveInShadowDom;
directiveInShadowDom = new TestDirective(
null, () => { orderOfOperations.push(directiveInShadowDom); });
var parentDirective;
parentDirective =
new TestDirective(null, () => { orderOfOperations.push(parentDirective); });
parent.hydrate(_DEFAULT_CONTEXT, null, new FakeDirectives([parentDirective], []),
null);
child.hydrate(_DEFAULT_CONTEXT, null,
new FakeDirectives([directiveInShadowDom], []), null);
parent.detectChanges();
expect(orderOfOperations).toEqual([directiveInShadowDom, parentDirective]);
});
});
});
}); });
}); });
@ -1104,21 +1270,17 @@ class TestDirective {
a; a;
b; b;
changes; changes;
afterContentCheckedCalled; doCheckCalled = false;
afterContentCheckedSpy; onInitCalled = false;
doCheckCalled;
onInitCalled; afterContentInitCalled = false;
afterContentCheckedCalled = false;
afterViewInitCalled = false;
afterViewCheckedCalled = false;
event; event;
constructor(onChangesDoneSpy = null) { constructor(public afterContentCheckedSpy = null, public afterViewCheckedSpy = null) {}
this.afterContentCheckedCalled = false;
this.doCheckCalled = false;
this.onInitCalled = false;
this.afterContentCheckedSpy = onChangesDoneSpy;
this.a = null;
this.b = null;
this.changes = null;
}
onEvent(event) { this.event = event; } onEvent(event) { this.event = event; }
@ -1132,12 +1294,23 @@ class TestDirective {
this.changes = r; this.changes = r;
} }
afterContentInit() { this.afterContentInitCalled = true; }
afterContentChecked() { afterContentChecked() {
this.afterContentCheckedCalled = true; this.afterContentCheckedCalled = true;
if (isPresent(this.afterContentCheckedSpy)) { if (isPresent(this.afterContentCheckedSpy)) {
this.afterContentCheckedSpy(); this.afterContentCheckedSpy();
} }
} }
afterViewInit() { this.afterViewInitCalled = true; }
afterViewChecked() {
this.afterViewCheckedCalled = true;
if (isPresent(this.afterViewCheckedSpy)) {
this.afterViewCheckedSpy();
}
}
} }
class Person { class Person {
@ -1183,6 +1356,7 @@ class TestDispatcher implements ChangeDispatcher {
debugLog: string[]; debugLog: string[];
loggedValues: List<any>; loggedValues: List<any>;
afterContentCheckedCalled: boolean = false; afterContentCheckedCalled: boolean = false;
afterViewCheckedCalled: boolean = false;
constructor() { this.clear(); } constructor() { this.clear(); }
@ -1201,6 +1375,7 @@ class TestDispatcher implements ChangeDispatcher {
logBindingUpdate(target, value) { this.debugLog.push(`${target.name}=${this._asString(value)}`); } logBindingUpdate(target, value) { this.debugLog.push(`${target.name}=${this._asString(value)}`); }
notifyAfterContentChecked() { this.afterContentCheckedCalled = true; } notifyAfterContentChecked() { this.afterContentCheckedCalled = true; }
notifyAfterViewChecked() { this.afterViewCheckedCalled = true; }
getDebugContext(a, b) { return null; } getDebugContext(a, b) { return null; }

View File

@ -88,6 +88,25 @@ main() {
}); });
}); });
describe("afterContentInit", () {
it("should be true when the directive implements AfterContentInit", () {
expect(
metadata(DirectiveImplementingAfterContentInit, new Directive())
.callAfterContentInit).toBe(true);
});
it("should be true when the lifecycle includes afterContentInit", () {
expect(metadata(DirectiveNoHooks,
new Directive(lifecycle: [LifecycleEvent.AfterContentInit]))
.callAfterContentInit).toBe(true);
});
it("should be false otherwise", () {
expect(metadata(DirectiveNoHooks, new Directive())
.callAfterContentInit).toBe(false);
});
});
describe("afterContentChecked", () { describe("afterContentChecked", () {
it("should be true when the directive implements AfterContentChecked", () { it("should be true when the directive implements AfterContentChecked", () {
expect( expect(
@ -106,6 +125,44 @@ main() {
.callAfterContentChecked).toBe(false); .callAfterContentChecked).toBe(false);
}); });
}); });
describe("afterViewInit", () {
it("should be true when the directive implements AfterViewInit", () {
expect(
metadata(DirectiveImplementingAfterViewInit, new Directive())
.callAfterViewInit).toBe(true);
});
it("should be true when the lifecycle includes afterViewInit", () {
expect(metadata(DirectiveNoHooks,
new Directive(lifecycle: [LifecycleEvent.AfterViewInit]))
.callAfterViewInit).toBe(true);
});
it("should be false otherwise", () {
expect(metadata(DirectiveNoHooks, new Directive())
.callAfterViewInit).toBe(false);
});
});
describe("afterViewChecked", () {
it("should be true when the directive implements AfterViewChecked", () {
expect(
metadata(DirectiveImplementingAfterViewChecked, new Directive())
.callAfterViewChecked).toBe(true);
});
it("should be true when the lifecycle includes afterViewChecked", () {
expect(metadata(DirectiveNoHooks,
new Directive(lifecycle: [LifecycleEvent.AfterViewChecked]))
.callAfterViewChecked).toBe(true);
});
it("should be false otherwise", () {
expect(metadata(DirectiveNoHooks, new Directive())
.callAfterViewChecked).toBe(false);
});
});
}); });
}); });
} }
@ -128,6 +185,18 @@ class DirectiveImplementingOnDestroy implements OnDestroy {
onDestroy() {} onDestroy() {}
} }
class DirectiveImplementingAfterContentInit implements AfterContentInit {
afterContentInit() {}
}
class DirectiveImplementingAfterContentChecked implements AfterContentChecked { class DirectiveImplementingAfterContentChecked implements AfterContentChecked {
afterContentChecked() {} afterContentChecked() {}
} }
class DirectiveImplementingAfterViewInit implements AfterViewInit {
afterViewInit() {}
}
class DirectiveImplementingAfterViewChecked implements AfterViewChecked {
afterViewChecked() {}
}

View File

@ -102,6 +102,26 @@ export function main() {
}); });
}); });
describe("afterContentInit", () => {
it("should be true when the directive has the afterContentInit method", () => {
expect(metadata(DirectiveWithAfterContentInitMethod, new DirectiveMetadata({}))
.callAfterContentInit)
.toBe(true);
});
it("should be true when the lifecycle includes afterContentInit", () => {
expect(metadata(DirectiveNoHooks,
new DirectiveMetadata({lifecycle: [LifecycleEvent.AfterContentInit]}))
.callAfterContentInit)
.toBe(true);
});
it("should be false otherwise", () => {
expect(metadata(DirectiveNoHooks, new DirectiveMetadata()).callAfterContentInit)
.toBe(false);
});
});
describe("afterContentChecked", () => { describe("afterContentChecked", () => {
it("should be true when the directive has the afterContentChecked method", () => { it("should be true when the directive has the afterContentChecked method", () => {
expect(metadata(DirectiveWithAfterContentCheckedMethod, new DirectiveMetadata({})) expect(metadata(DirectiveWithAfterContentCheckedMethod, new DirectiveMetadata({}))
@ -121,6 +141,46 @@ export function main() {
.toBe(false); .toBe(false);
}); });
}); });
describe("afterViewInit", () => {
it("should be true when the directive has the afterViewInit method", () => {
expect(metadata(DirectiveWithAfterViewInitMethod, new DirectiveMetadata({}))
.callAfterViewInit)
.toBe(true);
});
it("should be true when the lifecycle includes afterViewInit", () => {
expect(metadata(DirectiveNoHooks,
new DirectiveMetadata({lifecycle: [LifecycleEvent.AfterViewInit]}))
.callAfterViewInit)
.toBe(true);
});
it("should be false otherwise", () => {
expect(metadata(DirectiveNoHooks, new DirectiveMetadata()).callAfterViewInit).toBe(false);
});
});
describe("afterViewChecked", () => {
it("should be true when the directive has the afterViewChecked method", () => {
expect(metadata(DirectiveWithAfterViewCheckedMethod, new DirectiveMetadata({}))
.callAfterViewChecked)
.toBe(true);
});
it("should be true when the lifecycle includes afterViewChecked", () => {
expect(metadata(DirectiveNoHooks,
new DirectiveMetadata({lifecycle: [LifecycleEvent.AfterViewChecked]}))
.callAfterViewChecked)
.toBe(true);
});
it("should be false otherwise", () => {
expect(metadata(DirectiveNoHooks, new DirectiveMetadata()).callAfterViewChecked)
.toBe(false);
});
});
}); });
}); });
} }
@ -143,6 +203,18 @@ class DirectiveWithOnDestroyMethod {
onDestroy(_) {} onDestroy(_) {}
} }
class DirectiveWithAfterContentInitMethod {
afterContentInit() {}
}
class DirectiveWithAfterContentCheckedMethod { class DirectiveWithAfterContentCheckedMethod {
afterContentChecked() {} afterContentChecked() {}
} }
class DirectiveWithAfterViewInitMethod {
afterViewInit() {}
}
class DirectiveWithAfterViewCheckedMethod {
afterViewChecked() {}
}

View File

@ -9,6 +9,7 @@ import {
it, it,
xdescribe, xdescribe,
xit, xit,
Log,
TestComponentBuilder TestComponentBuilder
} from 'angular2/test_lib'; } from 'angular2/test_lib';
@ -18,28 +19,26 @@ export function main() {
describe('directive lifecycle integration spec', () => { describe('directive lifecycle integration spec', () => {
it('should invoke lifecycle methods onChanges > onInit > doCheck > afterContentChecked', it('should invoke lifecycle methods onChanges > onInit > doCheck > afterContentChecked',
inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async) => { inject([TestComponentBuilder, Log, AsyncTestCompleter], (tcb: TestComponentBuilder, log: Log,
async) => {
tcb.overrideView( tcb.overrideView(
MyComp, MyComp,
new ViewMetadata( new ViewMetadata(
{template: '<div [field]="123" lifecycle></div>', directives: [LifecycleDir]})) {template: '<div [field]="123" lifecycle></div>', directives: [LifecycleCmp]}))
.createAsync(MyComp) .createAsync(MyComp)
.then((tc) => { .then((tc) => {
var dir = tc.componentViewChildren[0].inject(LifecycleDir);
tc.detectChanges(); tc.detectChanges();
expect(dir.log).toEqual(["onChanges", "onInit", "doCheck", "afterContentChecked"]); expect(log.result())
.toEqual(
"onChanges; onInit; doCheck; afterContentInit; afterContentChecked; child_doCheck; " +
"afterViewInit; afterViewChecked");
log.clear();
tc.detectChanges(); tc.detectChanges();
expect(dir.log).toEqual([ expect(log.result())
"onChanges", .toEqual("doCheck; afterContentChecked; child_doCheck; afterViewChecked");
"onInit",
"doCheck",
"afterContentChecked",
"doCheck",
"afterContentChecked"
]);
async.done(); async.done();
}); });
@ -48,29 +47,43 @@ export function main() {
} }
@Directive({ @Directive({selector: '[lifecycle-dir]', lifecycle: [LifecycleEvent.DoCheck]})
class LifecycleDir {
constructor(private log: Log) {}
doCheck() { this.log.add("child_doCheck"); }
}
@Component({
selector: "[lifecycle]", selector: "[lifecycle]",
properties: ['field'], properties: ['field'],
lifecycle: [ lifecycle: [
LifecycleEvent.OnChanges, LifecycleEvent.OnChanges,
LifecycleEvent.DoCheck,
LifecycleEvent.OnInit, LifecycleEvent.OnInit,
LifecycleEvent.AfterContentChecked LifecycleEvent.DoCheck,
LifecycleEvent.AfterContentInit,
LifecycleEvent.AfterContentChecked,
LifecycleEvent.AfterViewInit,
LifecycleEvent.AfterViewChecked
] ]
}) })
class LifecycleDir { @View({template: `<div lifecycle-dir></div>`, directives: [LifecycleDir]})
class LifecycleCmp {
field; field;
log: List<string>; constructor(private log: Log) {}
constructor() { this.log = []; } onChanges(_) { this.log.add("onChanges"); }
onChanges(_) { this.log.push("onChanges"); } onInit() { this.log.add("onInit"); }
onInit() { this.log.push("onInit"); } doCheck() { this.log.add("doCheck"); }
doCheck() { this.log.push("doCheck"); } afterContentInit() { this.log.add("afterContentInit"); }
afterContentChecked() { this.log.push("afterContentChecked"); } afterContentChecked() { this.log.add("afterContentChecked"); }
afterViewInit() { this.log.add("afterViewInit"); }
afterViewChecked() { this.log.add("afterViewChecked"); }
} }
@Component({selector: 'my-comp'}) @Component({selector: 'my-comp'})

View File

@ -389,4 +389,5 @@ class DummyDispatcher implements ChangeDispatcher {
notifyOnBinding(bindingTarget, newValue) { throw "Should not be used"; } notifyOnBinding(bindingTarget, newValue) { throw "Should not be used"; }
logBindingUpdate(bindingTarget, newValue) { throw "Should not be used"; } logBindingUpdate(bindingTarget, newValue) { throw "Should not be used"; }
notifyAfterContentChecked() {} notifyAfterContentChecked() {}
notifyAfterViewChecked() {}
} }

View File

@ -27,7 +27,10 @@ Map<String, dynamic> directiveMetadataToMap(RenderDirectiveMetadata meta) {
["callDoCheck", meta.callDoCheck], ["callDoCheck", meta.callDoCheck],
["callOnInit", meta.callOnInit], ["callOnInit", meta.callOnInit],
["callOnChanges", meta.callOnChanges], ["callOnChanges", meta.callOnChanges],
["callAfterContentInit", meta.callAfterContentInit],
["callAfterContentChecked", meta.callAfterContentChecked], ["callAfterContentChecked", meta.callAfterContentChecked],
["callAfterViewInit", meta.callAfterViewInit],
["callAfterViewChecked", meta.callAfterViewChecked],
["events", meta.events], ["events", meta.events],
["changeDetection", meta.changeDetection == null ? null : meta.changeDetection.index], ["changeDetection", meta.changeDetection == null ? null : meta.changeDetection.index],
["version", 1] ["version", 1]
@ -57,7 +60,10 @@ RenderDirectiveMetadata directiveMetadataFromMap(Map<String, dynamic> map) {
callDoCheck: (map["callDoCheck"] as bool), callDoCheck: (map["callDoCheck"] as bool),
callOnChanges: (map["callOnChanges"] as bool), callOnChanges: (map["callOnChanges"] as bool),
callOnInit: (map["callOnInit"] as bool), callOnInit: (map["callOnInit"] as bool),
callAfterContentInit: (map["callAfterContentInit"] as bool),
callAfterContentChecked: (map["callAfterContentChecked"] as bool), callAfterContentChecked: (map["callAfterContentChecked"] as bool),
callAfterViewInit: (map["callAfterViewInit"] as bool),
callAfterViewChecked: (map["callAfterViewChecked"] as bool),
events: (_cloneIfPresent(map["events"]) as List<String>), events: (_cloneIfPresent(map["events"]) as List<String>),
changeDetection: map["changeDetection"] == null ? null changeDetection: map["changeDetection"] == null ? null
: ChangeDetectionStrategy.values[map["changeDetection"] as int]); : ChangeDetectionStrategy.values[map["changeDetection"] as int]);

View File

@ -63,7 +63,10 @@ class _DirectiveMetadataVisitor extends Object
bool _callOnChange; bool _callOnChange;
bool _callOnCheck; bool _callOnCheck;
bool _callOnInit; bool _callOnInit;
bool _callAfterContentInit;
bool _callAfterContentChecked; bool _callAfterContentChecked;
bool _callAfterViewInit;
bool _callAfterViewChecked;
ChangeDetectionStrategy _changeDetection; ChangeDetectionStrategy _changeDetection;
List<String> _events; List<String> _events;
@ -83,7 +86,10 @@ class _DirectiveMetadataVisitor extends Object
_callOnChange = false; _callOnChange = false;
_callOnCheck = false; _callOnCheck = false;
_callOnInit = false; _callOnInit = false;
_callAfterContentInit = false;
_callAfterContentChecked = false; _callAfterContentChecked = false;
_callAfterViewInit = false;
_callAfterViewChecked = false;
_changeDetection = null; _changeDetection = null;
_events = []; _events = [];
} }
@ -100,7 +106,10 @@ class _DirectiveMetadataVisitor extends Object
callOnChanges: _callOnChange, callOnChanges: _callOnChange,
callDoCheck: _callOnCheck, callDoCheck: _callOnCheck,
callOnInit: _callOnInit, callOnInit: _callOnInit,
callAfterContentInit: _callAfterContentInit,
callAfterContentChecked: _callAfterContentChecked, callAfterContentChecked: _callAfterContentChecked,
callAfterViewInit: _callAfterViewInit,
callAfterViewChecked: _callAfterViewChecked,
changeDetection: _changeDetection, changeDetection: _changeDetection,
events: _events); events: _events);
@ -274,7 +283,10 @@ class _DirectiveMetadataVisitor extends Object
_callOnChange = lifecycleEvents.contains("OnChanges"); _callOnChange = lifecycleEvents.contains("OnChanges");
_callOnCheck = lifecycleEvents.contains("DoCheck"); _callOnCheck = lifecycleEvents.contains("DoCheck");
_callOnInit = lifecycleEvents.contains("OnInit"); _callOnInit = lifecycleEvents.contains("OnInit");
_callAfterContentInit = lifecycleEvents.contains("AfterContentInit");
_callAfterContentChecked = lifecycleEvents.contains("AfterContentChecked"); _callAfterContentChecked = lifecycleEvents.contains("AfterContentChecked");
_callAfterViewInit = lifecycleEvents.contains("AfterViewInit");
_callAfterViewChecked = lifecycleEvents.contains("AfterViewChecked");
} }
void _populateEvents(Expression eventsValue) { void _populateEvents(Expression eventsValue) {

View File

@ -33,13 +33,34 @@ const _ON_INIT_INTERFACES = const [
const ClassDescriptor( const ClassDescriptor(
'OnInit', 'package:angular2/src/core/compiler/interfaces.dart'), 'OnInit', 'package:angular2/src/core/compiler/interfaces.dart'),
]; ];
const _ON_ALL_CHANGES_DONE_INTERFACES = const [ const _ON_AFTER_CONTENT_INIT_INTERFACES = const [
const ClassDescriptor('AfterContentInit', 'package:angular2/angular2.dart'),
const ClassDescriptor(
'AfterContentInit', 'package:angular2/metadata.dart'),
const ClassDescriptor(
'AfterContentInit', 'package:angular2/src/core/compiler/interfaces.dart')
];
const _ON_AFTER_CONTENT_CHECKED_INTERFACES = const [
const ClassDescriptor('AfterContentChecked', 'package:angular2/angular2.dart'), const ClassDescriptor('AfterContentChecked', 'package:angular2/angular2.dart'),
const ClassDescriptor( const ClassDescriptor(
'AfterContentChecked', 'package:angular2/metadata.dart'), 'AfterContentChecked', 'package:angular2/metadata.dart'),
const ClassDescriptor( const ClassDescriptor(
'AfterContentChecked', 'package:angular2/src/core/compiler/interfaces.dart') 'AfterContentChecked', 'package:angular2/src/core/compiler/interfaces.dart')
]; ];
const _ON_AFTER_VIEW_INIT_INTERFACES = const [
const ClassDescriptor('AfterViewInit', 'package:angular2/angular2.dart'),
const ClassDescriptor(
'AfterViewInit', 'package:angular2/metadata.dart'),
const ClassDescriptor(
'AfterViewInit', 'package:angular2/src/core/compiler/interfaces.dart')
];
const _ON_AFTER_VIEW_CHECKED_INTERFACES = const [
const ClassDescriptor('AfterViewChecked', 'package:angular2/angular2.dart'),
const ClassDescriptor(
'AfterViewChecked', 'package:angular2/metadata.dart'),
const ClassDescriptor(
'AfterViewChecked', 'package:angular2/src/core/compiler/interfaces.dart')
];
/// Checks if a given [Annotation] matches any of the given /// Checks if a given [Annotation] matches any of the given
/// [ClassDescriptors]. /// [ClassDescriptors].
@ -52,7 +73,10 @@ class InterfaceMatcher extends ClassMatcherBase {
..addAll(_ON_DESTROY_INTERFACES) ..addAll(_ON_DESTROY_INTERFACES)
..addAll(_ON_CHECK_INTERFACES) ..addAll(_ON_CHECK_INTERFACES)
..addAll(_ON_INIT_INTERFACES) ..addAll(_ON_INIT_INTERFACES)
..addAll(_ON_ALL_CHANGES_DONE_INTERFACES)); ..addAll(_ON_AFTER_CONTENT_INIT_INTERFACES)
..addAll(_ON_AFTER_CONTENT_CHECKED_INTERFACES)
..addAll(_ON_AFTER_VIEW_INIT_INTERFACES)
..addAll(_ON_AFTER_VIEW_CHECKED_INTERFACES));
} }
/// Checks if an [Identifier] implements [OnChanges]. /// Checks if an [Identifier] implements [OnChanges].
@ -71,7 +95,19 @@ class InterfaceMatcher extends ClassMatcherBase {
bool isOnInit(Identifier typeName, AssetId assetId) => bool isOnInit(Identifier typeName, AssetId assetId) =>
implements(firstMatch(typeName, assetId), _ON_INIT_INTERFACES); implements(firstMatch(typeName, assetId), _ON_INIT_INTERFACES);
/// Checks if an [Identifier] implements [AfterContentInit].
bool isAfterContentInit(Identifier typeName, AssetId assetId) => implements(
firstMatch(typeName, assetId), _ON_AFTER_CONTENT_INIT_INTERFACES);
/// Checks if an [Identifier] implements [AfterContentChecked]. /// Checks if an [Identifier] implements [AfterContentChecked].
bool isAfterContentChecked(Identifier typeName, AssetId assetId) => implements( bool isAfterContentChecked(Identifier typeName, AssetId assetId) => implements(
firstMatch(typeName, assetId), _ON_ALL_CHANGES_DONE_INTERFACES); firstMatch(typeName, assetId), _ON_AFTER_CONTENT_CHECKED_INTERFACES);
/// Checks if an [Identifier] implements [AfterViewInit].
bool isAfterViewInit(Identifier typeName, AssetId assetId) => implements(
firstMatch(typeName, assetId), _ON_AFTER_VIEW_INIT_INTERFACES);
/// Checks if an [Identifier] implements [AfterViewChecked].
bool isAfterViewChecked(Identifier typeName, AssetId assetId) => implements(
firstMatch(typeName, assetId), _ON_AFTER_VIEW_CHECKED_INTERFACES);
} }

View File

@ -271,10 +271,22 @@ class AnnotationsTransformVisitor extends ToSourceVisitor {
_ifaceLifecycleEntries.add('${LifecycleEvent.OnInit}'); _ifaceLifecycleEntries.add('${LifecycleEvent.OnInit}');
populateImport(name); populateImport(name);
} }
if (_interfaceMatcher.isAfterContentInit(name, _assetId)) {
_ifaceLifecycleEntries.add('${LifecycleEvent.AfterContentInit}');
populateImport(name);
}
if (_interfaceMatcher.isAfterContentChecked(name, _assetId)) { if (_interfaceMatcher.isAfterContentChecked(name, _assetId)) {
_ifaceLifecycleEntries.add('${LifecycleEvent.AfterContentChecked}'); _ifaceLifecycleEntries.add('${LifecycleEvent.AfterContentChecked}');
populateImport(name); populateImport(name);
} }
if (_interfaceMatcher.isAfterViewInit(name, _assetId)) {
_ifaceLifecycleEntries.add('${LifecycleEvent.AfterViewInit}');
populateImport(name);
}
if (_interfaceMatcher.isAfterViewChecked(name, _assetId)) {
_ifaceLifecycleEntries.add('${LifecycleEvent.AfterViewChecked}');
populateImport(name);
}
}); });
} }

View File

@ -143,15 +143,15 @@ class _CodegenState {
var $_CHANGES_LOCAL = null; var $_CHANGES_LOCAL = null;
${_records.map(_genRecord).join('')} ${_records.map(_genRecord).join('')}
${_names.getAlreadyCheckedName()} = true;
} }
${_maybeGenHandleEventInternal()} ${_maybeGenHandleEventInternal()}
${_genCheckNoChanges()} ${_genCheckNoChanges()}
${_maybeGenCallAfterContentChecked()} ${_maybeGenAfterContentLifecycleCallbacks()}
${_maybeGenAfterViewLifecycleCallbacks()}
${_maybeGenHydrateDirectives()} ${_maybeGenHydrateDirectives()}
@ -260,19 +260,24 @@ class _CodegenState {
'{ $hydrateDirectivesCode $hydrateDetectorsCode }'; '{ $hydrateDirectivesCode $hydrateDetectorsCode }';
} }
/// Generates calls to `afterContentChecked` for all `Directive`s that request String _maybeGenAfterContentLifecycleCallbacks() {
/// them. var directiveNotifications = _logic.genContentLifecycleCallbacks(_directiveRecords);
String _maybeGenCallAfterContentChecked() {
// NOTE(kegluneq): Order is important!
var directiveNotifications = _directiveRecords.reversed
.where((rec) => rec.callAfterContentChecked)
.map((rec) =>
'${_names.getDirectiveName(rec.directiveIndex)}.afterContentChecked();');
if (directiveNotifications.isNotEmpty) { if (directiveNotifications.isNotEmpty) {
return ''' return '''
void callAfterContentChecked() { void afterContentLifecycleCallbacksInternal() {
${_names.getDispatcherName()}.notifyAfterContentChecked(); ${directiveNotifications.join('')}
}
''';
} else {
return '';
}
}
String _maybeGenAfterViewLifecycleCallbacks() {
var directiveNotifications = _logic.genViewLifecycleCallbacks(_directiveRecords);
if (directiveNotifications.isNotEmpty) {
return '''
void afterViewLifecycleCallbacksInternal() {
${directiveNotifications.join('')} ${directiveNotifications.join('')}
} }
'''; ''';

View File

@ -26,7 +26,10 @@ main() {
callOnChanges: true, callOnChanges: true,
callDoCheck: true, callDoCheck: true,
callOnInit: true, callOnInit: true,
callAfterContentInit: true,
callAfterContentChecked: true, callAfterContentChecked: true,
callAfterViewInit: true,
callAfterViewChecked: true,
events: ["onFoo", "onBar"], events: ["onFoo", "onBar"],
changeDetection: ChangeDetectionStrategy.CheckOnce); changeDetection: ChangeDetectionStrategy.CheckOnce);
var map = directiveMetadataToMap(someComponent); var map = directiveMetadataToMap(someComponent);
@ -46,7 +49,10 @@ main() {
expect(map["callDoCheck"]).toEqual(true); expect(map["callDoCheck"]).toEqual(true);
expect(map["callOnChanges"]).toEqual(true); expect(map["callOnChanges"]).toEqual(true);
expect(map["callOnInit"]).toEqual(true); expect(map["callOnInit"]).toEqual(true);
expect(map["callAfterContentInit"]).toEqual(true);
expect(map["callAfterContentChecked"]).toEqual(true); expect(map["callAfterContentChecked"]).toEqual(true);
expect(map["callAfterViewInit"]).toEqual(true);
expect(map["callAfterViewChecked"]).toEqual(true);
expect(map["exportAs"]).toEqual("aaa"); expect(map["exportAs"]).toEqual("aaa");
expect(map["events"]).toEqual(["onFoo", "onBar"]); expect(map["events"]).toEqual(["onFoo", "onBar"]);
expect(map["changeDetection"]).toEqual(ChangeDetectionStrategy.CheckOnce.index); expect(map["changeDetection"]).toEqual(ChangeDetectionStrategy.CheckOnce.index);
@ -67,7 +73,10 @@ main() {
["callDoCheck", true], ["callDoCheck", true],
["callOnInit", true], ["callOnInit", true],
["callOnChanges", true], ["callOnChanges", true],
["callAfterContentInit", true],
["callAfterContentChecked", true], ["callAfterContentChecked", true],
["callAfterViewInit", true],
["callAfterViewChecked", true],
["events", ["onFoo", "onBar"]], ["events", ["onFoo", "onBar"]],
["changeDetection", ChangeDetectionStrategy.CheckOnce.index] ["changeDetection", ChangeDetectionStrategy.CheckOnce.index]
]); ]);
@ -89,7 +98,10 @@ main() {
expect(meta.callDoCheck).toEqual(true); expect(meta.callDoCheck).toEqual(true);
expect(meta.callOnInit).toEqual(true); expect(meta.callOnInit).toEqual(true);
expect(meta.callOnChanges).toEqual(true); expect(meta.callOnChanges).toEqual(true);
expect(meta.callAfterContentInit).toEqual(true);
expect(meta.callAfterContentChecked).toEqual(true); expect(meta.callAfterContentChecked).toEqual(true);
expect(meta.callAfterViewInit).toEqual(true);
expect(meta.callAfterViewChecked).toEqual(true);
expect(meta.events).toEqual(["onFoo", "onBar"]); expect(meta.events).toEqual(["onFoo", "onBar"]);
expect(meta.changeDetection).toEqual(ChangeDetectionStrategy.CheckOnce); expect(meta.changeDetection).toEqual(ChangeDetectionStrategy.CheckOnce);
}); });

View File

@ -106,7 +106,10 @@ void allTests() {
expect(metadata.callOnChanges).toBe(true); expect(metadata.callOnChanges).toBe(true);
expect(metadata.callDoCheck).toBe(true); expect(metadata.callDoCheck).toBe(true);
expect(metadata.callOnInit).toBe(true); expect(metadata.callOnInit).toBe(true);
expect(metadata.callAfterContentInit).toBe(true);
expect(metadata.callAfterContentChecked).toBe(true); expect(metadata.callAfterContentChecked).toBe(true);
expect(metadata.callAfterViewInit).toBe(true);
expect(metadata.callAfterViewChecked).toBe(true);
}); });
it('should parse events.', () async { it('should parse events.', () async {

View File

@ -17,7 +17,10 @@ void initReflector(reflector) {
LifecycleEvent.OnDestroy, LifecycleEvent.OnDestroy,
LifecycleEvent.OnInit, LifecycleEvent.OnInit,
LifecycleEvent.DoCheck, LifecycleEvent.DoCheck,
LifecycleEvent.AfterContentChecked LifecycleEvent.AfterContentInit,
LifecycleEvent.AfterContentChecked,
LifecycleEvent.AfterViewInit,
LifecycleEvent.AfterViewChecked
]) ])
], const [ ], const [
const [] const []

View File

@ -52,6 +52,17 @@ void initReflector() {
const [], const [],
() => new OnInitSoupComponent(), () => new OnInitSoupComponent(),
const [OnInit])) const [OnInit]))
..registerType(
AfterContentInitSoupComponent,
new _ngRef.ReflectionInfo(
const [
const Component(
selector: '[soup]',
lifecycle: const [LifecycleEvent.AfterContentInit])
],
const [],
() => new AfterContentInitSoupComponent(),
const [AfterContentInit]))
..registerType( ..registerType(
AfterContentCheckedSoupComponent, AfterContentCheckedSoupComponent,
new _ngRef.ReflectionInfo( new _ngRef.ReflectionInfo(
@ -62,5 +73,27 @@ void initReflector() {
], ],
const [], const [],
() => new AfterContentCheckedSoupComponent(), () => new AfterContentCheckedSoupComponent(),
const [AfterContentChecked])); const [AfterContentChecked]))
..registerType(
AfterViewInitSoupComponent,
new _ngRef.ReflectionInfo(
const [
const Component(
selector: '[soup]',
lifecycle: const [LifecycleEvent.AfterViewInit])
],
const [],
() => new AfterViewInitSoupComponent(),
const [AfterViewInit]))
..registerType(
AfterViewCheckedSoupComponent,
new _ngRef.ReflectionInfo(
const [
const Component(
selector: '[soup]',
lifecycle: const [LifecycleEvent.AfterViewChecked])
],
const [],
() => new AfterViewCheckedSoupComponent(),
const [AfterViewChecked]));
} }

View File

@ -14,5 +14,14 @@ class OnCheckSoupComponent implements DoCheck {}
@Component(selector: '[soup]') @Component(selector: '[soup]')
class OnInitSoupComponent implements OnInit {} class OnInitSoupComponent implements OnInit {}
@Component(selector: '[soup]')
class AfterContentInitSoupComponent implements AfterContentInit {}
@Component(selector: '[soup]') @Component(selector: '[soup]')
class AfterContentCheckedSoupComponent implements AfterContentChecked {} class AfterContentCheckedSoupComponent implements AfterContentChecked {}
@Component(selector: '[soup]')
class AfterViewInitSoupComponent implements AfterViewInit {}
@Component(selector: '[soup]')
class AfterViewCheckedSoupComponent implements AfterViewChecked {}

View File

@ -16,7 +16,10 @@
"callDoCheck": false, "callDoCheck": false,
"callOnInit": false, "callOnInit": false,
"callOnChanges": false, "callOnChanges": false,
"callAfterContentInit": false,
"callAfterContentChecked": false, "callAfterContentChecked": false,
"callAfterViewInit": false,
"callAfterViewChecked": false,
"events": [], "events": [],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1

View File

@ -66,8 +66,6 @@ class _MyComponent_ChangeDetector0
changes = null; changes = null;
isChanged = false; isChanged = false;
this.alreadyChecked = true;
} }
void checkNoChanges() { void checkNoChanges() {

View File

@ -16,7 +16,10 @@
"callDoCheck": null, "callDoCheck": null,
"callOnInit": null, "callOnInit": null,
"callOnChanges": null, "callOnChanges": null,
"callAfterContentInit": null,
"callAfterContentChecked": null, "callAfterContentChecked": null,
"callAfterViewInit": null,
"callAfterViewChecked": null,
"events": ["dependencyEventName"], "events": ["dependencyEventName"],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -39,7 +42,10 @@
"callDoCheck": null, "callDoCheck": null,
"callOnInit": null, "callOnInit": null,
"callOnChanges": null, "callOnChanges": null,
"callAfterContentInit": null,
"callAfterContentChecked": null, "callAfterContentChecked": null,
"callAfterViewInit": null,
"callAfterViewChecked": null,
"events": null, "events": null,
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -62,7 +68,10 @@
"callDoCheck": null, "callDoCheck": null,
"callOnInit": null, "callOnInit": null,
"callOnChanges": null, "callOnChanges": null,
"callAfterContentInit": null,
"callAfterContentChecked": null, "callAfterContentChecked": null,
"callAfterViewInit": null,
"callAfterViewChecked": null,
"events": null, "events": null,
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -85,7 +94,10 @@
"callDoCheck": true, "callDoCheck": true,
"callOnInit": null, "callOnInit": null,
"callOnChanges": null, "callOnChanges": null,
"callAfterContentInit": null,
"callAfterContentChecked": null, "callAfterContentChecked": null,
"callAfterViewInit": null,
"callAfterViewChecked": null,
"events": null, "events": null,
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1

View File

@ -16,7 +16,10 @@
"callDoCheck": null, "callDoCheck": null,
"callOnInit": null, "callOnInit": null,
"callOnChanges": null, "callOnChanges": null,
"callAfterContentInit": null,
"callAfterContentChecked": null, "callAfterContentChecked": null,
"callAfterViewInit": null,
"callAfterViewChecked": null,
"events": null, "events": null,
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -39,7 +42,10 @@
"callDoCheck": false, "callDoCheck": false,
"callOnInit": false, "callOnInit": false,
"callOnChanges": false, "callOnChanges": false,
"callAfterContentInit": false,
"callAfterContentChecked": false, "callAfterContentChecked": false,
"callAfterViewInit": false,
"callAfterViewChecked": false,
"events": [], "events": [],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -62,7 +68,10 @@
"callDoCheck": false, "callDoCheck": false,
"callOnInit": false, "callOnInit": false,
"callOnChanges": false, "callOnChanges": false,
"callAfterContentInit": false,
"callAfterContentChecked": false, "callAfterContentChecked": false,
"callAfterViewInit": false,
"callAfterViewChecked": false,
"events": ["eventName"], "events": ["eventName"],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -85,7 +94,10 @@
"callDoCheck": false, "callDoCheck": false,
"callOnInit": false, "callOnInit": false,
"callOnChanges": false, "callOnChanges": false,
"callAfterContentInit": false,
"callAfterContentChecked": false, "callAfterContentChecked": false,
"callAfterViewInit": false,
"callAfterViewChecked": false,
"events": [], "events": [],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -108,7 +120,10 @@
"callDoCheck": false, "callDoCheck": false,
"callOnInit": false, "callOnInit": false,
"callOnChanges": false, "callOnChanges": false,
"callAfterContentInit": false,
"callAfterContentChecked": false, "callAfterContentChecked": false,
"callAfterViewInit": false,
"callAfterViewChecked": false,
"events": [], "events": [],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -131,7 +146,10 @@
"callDoCheck": false, "callDoCheck": false,
"callOnInit": false, "callOnInit": false,
"callOnChanges": false, "callOnChanges": false,
"callAfterContentInit": false,
"callAfterContentChecked": false, "callAfterContentChecked": false,
"callAfterViewInit": false,
"callAfterViewChecked": false,
"events": [], "events": [],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -154,7 +172,10 @@
"callDoCheck": false, "callDoCheck": false,
"callOnInit": false, "callOnInit": false,
"callOnChanges": false, "callOnChanges": false,
"callAfterContentInit": false,
"callAfterContentChecked": false, "callAfterContentChecked": false,
"callAfterViewInit": false,
"callAfterViewChecked": false,
"events": [], "events": [],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1
@ -177,7 +198,10 @@
"callDoCheck": false, "callDoCheck": false,
"callOnInit": false, "callOnInit": false,
"callOnChanges": false, "callOnChanges": false,
"callAfterContentInit": false,
"callAfterContentChecked": false, "callAfterContentChecked": false,
"callAfterViewInit": false,
"callAfterViewChecked": false,
"events": [], "events": [],
"changeDetection": null, "changeDetection": null,
"version": 1 "version": 1