+ `,
+ styles: ['.parent {background: burlywood; padding: 8px; margin:100px 8px;}'],
+ directives: [ChildComponent],
+ providers:[LoggerService]
+})
+export class AfterViewParentComponent
+ implements AfterContentInit, AfterViewChecked, AfterViewInit {
+
+ private _logger:LoggerService;
+
+ constructor(logger:LoggerService){
+ this._logger = logger;
+ this.hookLog = logger.logs;
+ logger.log('AfterView ctor: ' + this._getMessage());
+ }
+
+ hookLog:string[];
+ hero = 'Magneta';
+ showChild = true;
+
+ // Query for a CONTENT child of type `ChildComponent`
+ // No such CONTENT child exists!
+ // This component holds a view but no content of that type.
+ @ContentChild(ChildComponent) contentChild: ChildComponent;
+
+ // Query for a VIEW child of type `ChildComponent`
+ @ViewChild(ChildComponent) viewChild: ChildComponent;
+
+
+ ///// Hooks
+ ngAfterContentInit() {
+ this._logger.log(`AfterContentInit: There is ${this.contentChild ? 'a' : 'no'} content child`);
+ }
+
+ ngAfterViewInit() {
+ // viewChild is set after the view has been initialized
+ this._logger.log('AfterViewInit: ' + this._getMessage());
+ }
+
+ private _prevHero:string;
+ ngAfterViewChecked() {
+ // viewChild is updated after the view has been checked
+ // Called frequently; only report when the hero changes
+ if (!this.viewChild || this._prevHero === this.viewChild.hero) {return;}
+ this._prevHero = this.viewChild.hero;
+ this._logger.log('AfterViewChecked: ' + this._getMessage());
+ }
+
+ private _getMessage(): string {
+ let cmp = this.viewChild;
+ return cmp ? `"${cmp.hero}" child view` : 'no child view';
+ }
+
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts
new file mode 100644
index 0000000000..14f1bdab24
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/app/app.component.ts
@@ -0,0 +1,43 @@
+// #docregion
+import {Component} from 'angular2/core';
+
+import {AfterContentParentComponent} from './after-content.component';
+import {AfterViewParentComponent} from './after-view.component';
+import {CounterParentComponent} from './counter.component';
+import {OnChangesParentComponent} from './on-changes.component';
+import {PeekABooParentComponent} from './peek-a-boo-parent.component';
+import {SpyParentComponent} from './spy.component';
+
+/***************************************/
+/*
+ template: `
+
+
+
+
+
+
+ `,
+ */
+
+@Component({
+ selector: 'my-app',
+ template: `
+
+
+
+
+
+
+ `,
+ directives: [
+ AfterContentParentComponent,
+ AfterViewParentComponent,
+ OnChangesParentComponent,
+ PeekABooParentComponent,
+ SpyParentComponent,
+ CounterParentComponent
+ ]
+})
+export class AppComponent {
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/boot.ts b/public/docs/_examples/lifecycle-hooks/ts/app/boot.ts
new file mode 100644
index 0000000000..4651bd780a
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/app/boot.ts
@@ -0,0 +1,4 @@
+import {bootstrap} from 'angular2/platform/browser';
+import {AppComponent} from './app.component';
+
+bootstrap(AppComponent).catch(err => console.error(err));
\ No newline at end of file
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/child.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/child.component.ts
new file mode 100644
index 0000000000..a027d9180c
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/app/child.component.ts
@@ -0,0 +1,20 @@
+// #docregion
+import {Component, Input} from 'angular2/core';
+
+@Component({
+ selector: 'my-child',
+ template: `
+
+
-- child view begins --
+
{{hero}} is my hero.
+
-- child view ends --
+
+ `,
+ styles: [
+ '.child {background: Yellow; padding: 8px; }',
+ '.my-child {background: LightYellow; padding: 8px; margin-top: 8px}'
+ ]
+})
+export class ChildComponent {
+ @Input() hero: string;
+}
\ No newline at end of file
diff --git a/public/docs/_examples/lifecycle-hooks/ts/app/counter.component.ts b/public/docs/_examples/lifecycle-hooks/ts/app/counter.component.ts
new file mode 100644
index 0000000000..7a502a25b0
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/app/counter.component.ts
@@ -0,0 +1,86 @@
+// #docregion
+import {
+ Component, Input, Output,
+ OnChanges, SimpleChange,
+} from 'angular2/core';
+
+import {Spy} from './spy.directive';
+import {LoggerService} from './logger.service';
+
+@Component({
+ selector: 'my-counter',
+ template: `
+
+ Counter = {{counter}}
+
+
-- Counter Change Log --
+
{{chg}}
+
+ `,
+ styles: ['.counter {background: LightYellow; padding: 8px; margin-top: 8px}'],
+ directives:[Spy]
+})
+export class MyCounter implements OnChanges {
+ @Input() counter: number;
+ changeLog:string[] = [];
+
+ ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
+
+ // Empty the changeLog whenever counter goes to zero
+ // hint: this is a way to respond programmatically to external value changes.
+ if (this.counter === 0) {
+ this.changeLog.length = 0;
+ }
+
+ // A change to `counter` is the only change we care about
+ let prop = changes['counter'];
+ let cur = prop.currentValue;
+ let prev = JSON.stringify(prop.previousValue); // first time is {}; after is integer
+ this.changeLog.push(`counter: currentValue = ${cur}, previousValue = ${prev}`);
+ }
+
+}
+
+/***************************************/
+
+@Component({
+ selector: 'counter-parent',
+ template: `
+
+@Directive({selector: '[my-spy]'})
+export class Spy implements OnInit, OnDestroy {
+
+ private _id = nextId++;
+ private _logger:LoggerService;
+
+ constructor(logger:LoggerService){
+ this._logger = logger;
+ }
+
+ ngOnInit() {
+ this._logIt(`onInit`);
+ }
+
+ ngOnDestroy() {
+ this._logIt(`onDestroy`);
+ }
+
+ private _logIt(msg:string){
+ this._logger.log(`Spy #${this._id } ${msg}`);
+ }
+}
diff --git a/public/docs/_examples/lifecycle-hooks/ts/example-config.json b/public/docs/_examples/lifecycle-hooks/ts/example-config.json
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/public/docs/_examples/lifecycle-hooks/ts/index.html b/public/docs/_examples/lifecycle-hooks/ts/index.html
new file mode 100644
index 0000000000..b706287879
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/index.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+ Angular 2 Lifecycle Hooks
+
+
+
+
+
+
+
+
+ Loading...
+
+
+
\ No newline at end of file
diff --git a/public/docs/_examples/lifecycle-hooks/ts/plnkr.json b/public/docs/_examples/lifecycle-hooks/ts/plnkr.json
new file mode 100644
index 0000000000..366b8325ce
--- /dev/null
+++ b/public/docs/_examples/lifecycle-hooks/ts/plnkr.json
@@ -0,0 +1,7 @@
+{
+ "description": "Lifecycle Hooks",
+ "files":["!**/*.d.ts", "!**/*.js"],
+ "tags": ["lifecycle", "hooks",
+ "onInit", "onDestroy", "onChange",
+ "ngOnInit", "ngOnDestroy", "ngOnChange"]
+}
\ No newline at end of file
diff --git a/public/docs/ts/latest/guide/_data.json b/public/docs/ts/latest/guide/_data.json
index adfa83188e..323f39208f 100644
--- a/public/docs/ts/latest/guide/_data.json
+++ b/public/docs/ts/latest/guide/_data.json
@@ -48,6 +48,11 @@
"intro": "Discover the basics of screen navigation with the Angular 2 router"
},
+ "lifecycle-hooks": {
+ "title": "Lifecycle Hooks",
+ "intro": "Angular calls lifecycle hook methods on our directives and components as it creates, changes, and destroys them."
+ },
+
"attribute-directives": {
"title": "Attribute Directives",
"intro": "Attribute directives attach behavior to elements."
diff --git a/public/docs/ts/latest/guide/lifecycle-hooks.jade b/public/docs/ts/latest/guide/lifecycle-hooks.jade
new file mode 100644
index 0000000000..2750797013
--- /dev/null
+++ b/public/docs/ts/latest/guide/lifecycle-hooks.jade
@@ -0,0 +1,90 @@
+include ../../../../_includes/_util-fns
+
+:marked
+ # Component Lifecycle
+ A Component has a lifecycle managed by Angular itself. Angular creates it, renders it, creates and renders its children,
+ checks it when its data-bound properties change, and destroys it before removing it from the DOM.
+
+ Angular offers **Lifecycle hooks**
+ that give us visibility into these key moments and the ability to act when they occur.
+
+ We cover these hooks in this chapter and demonstrate how they work in code.
+
+ [Live Example](/resources/live-examples/lifecycle-hooks/ts/plnkr.html)
+
+
+
+.l-main-section
+:marked
+ ## The Lifecycle Hooks
+ Directive and component instances have a lifecycle
+ as Angular creates, updates, and destroys them.
+
+ Developers can tap into key moments in that lifecycle by implementing
+ one or more of the "Lifecycle Hook" interfaces, all of them available
+ in the `angular2/core` library.
+
+ Here is the complete lifecycle hook interface inventory:
+
+ * `OnInit`
+ * `OnDestroy`
+ * `DoCheck`
+ * `OnChanges`
+ * `AfterContentInit`
+ * `AfterContentChecked`
+ * `AfterViewInit`
+ * `AfterViewChecked`
+
+ No directive or component will implement all of them and some of them only make
+ sense for components.
+
+ Each interface has a single hook method whose name is the interface name prefixed with `ng`.
+ For example, the `OnInit` interface has a hook method names `ngOnInit`.
+
+ Angular calls these hook methods in the following order:
+ * `ngOnChanges` - called when an input or output binding value changes
+ * `ngOnInit` - after the first `ngOnChanges`
+ * `ngDoCheck` - developer's custom change detection
+ * `ngAfterContentInit` - after component content initialized
+ * `ngAfterContentChecked` - after every check of component content
+ * `ngAfterViewInit` - after component's view(s) are initialized
+ * `ngAfterViewChecked` - after every check of a component's view(s)
+ * `ngOnDestroy` - just before the directive is destroyed.
+
+ The [live example](/resources/live-examples/lifecycle-hooks/ts/plnkr.html) demonstrates
+ these hooks.
+
+:marked
+ ## Peek-a-boo
+ The `PeekABooComponent` demonstrates all of the hooks in the same component.
+.l-sub-section
+ :marked
+ Except for `DoCheck`. If our component superseded regular Angular change detection
+ with its own change detection processing
+ we would also add a `ngDoCheck` method. We would **not** implement `ngOnChanges`.
+ We write either `ngOnChanges` or `ngDoCheck`, not both.
+
+ Custom change detection and `ngDoCheck` are on our documentation backlog.
+:marked
+ Peek-a-boo is a demo. We'd rarely if ever implement all interfaces like this in real life.
+
+ We look forward to explaining the Peek-a-boo example and the other lifecycle hook examples in
+ an update to this chapter. Meanwhile, please enjoy poking around in the
+ [code](/resources/live-examples/lifecycle-hooks/ts/plnkr.html).
+
+ ## Interface optional?
+ The lifecycle interfaces are optional.
+ We recommend adding them to benefit from TypeScript's strong typing and editor tooling.
+
+ But they disappear from the transpiled JavaScript.
+ Angular can't see them at runtime. And they are useless to someone developing in
+ a language without interfaces (such as pure JavaScript).
+
+ Fortunately, they aren't necessary.
+ We don't have to add the lifecycle hook interfaces to our directives and components to benefit from the hooks themselves.
+
+ Angular instead inspects our directive and component classes
+ and calls the hook methods *if they are defined*.
+ Angular will find and call methods like `ngOnInit()`, with or without the interfaces.