docs: lifecycle-hooks example - extract things (components, directives) into their own files (#40212)
This change is in line with Angular Style Guide rule 01-01 https://angular.io/guide/styleguide#style-01-01. PR Close #40212
This commit is contained in:
parent
9be9e466b1
commit
aea265bfc5
|
@ -0,0 +1,38 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
import { LoggerService } from './logger.service';
|
||||
|
||||
@Component({
|
||||
selector: 'after-content-parent',
|
||||
template: `
|
||||
<div class="parent">
|
||||
<h2>AfterContent</h2>
|
||||
|
||||
<div *ngIf="show">` +
|
||||
// #docregion parent-template
|
||||
`<after-content>
|
||||
<app-child></app-child>
|
||||
</after-content>`
|
||||
// #enddocregion parent-template
|
||||
+ `</div>
|
||||
|
||||
<h4>-- AfterContent Logs --</h4>
|
||||
<p><button (click)="reset()">Reset</button></p>
|
||||
<div *ngFor="let msg of logger.logs">{{msg}}</div>
|
||||
</div>
|
||||
`,
|
||||
styles: ['.parent {background: burlywood}'],
|
||||
providers: [LoggerService]
|
||||
})
|
||||
export class AfterContentParentComponent {
|
||||
show = true;
|
||||
|
||||
constructor(public logger: LoggerService) { }
|
||||
|
||||
reset() {
|
||||
this.logger.clear();
|
||||
// quickly remove and reload AfterContentComponent which recreates it
|
||||
this.show = false;
|
||||
this.logger.tick_then(() => this.show = true);
|
||||
}
|
||||
}
|
|
@ -2,18 +2,9 @@
|
|||
// #docregion
|
||||
import { AfterContentChecked, AfterContentInit, Component, ContentChild } from '@angular/core';
|
||||
|
||||
import { ChildComponent } from './child.component';
|
||||
import { LoggerService } from './logger.service';
|
||||
|
||||
//////////////////
|
||||
@Component({
|
||||
selector: 'app-child',
|
||||
template: '<input [(ngModel)]="hero">'
|
||||
})
|
||||
export class ChildComponent {
|
||||
hero = 'Magneta';
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
@Component({
|
||||
selector: 'after-content',
|
||||
// #docregion template
|
||||
|
@ -75,40 +66,3 @@ export class AfterContentComponent implements AfterContentChecked, AfterContentI
|
|||
// ...
|
||||
}
|
||||
// #enddocregion hooks
|
||||
|
||||
//////////////
|
||||
@Component({
|
||||
selector: 'after-content-parent',
|
||||
template: `
|
||||
<div class="parent">
|
||||
<h2>AfterContent</h2>
|
||||
|
||||
<div *ngIf="show">` +
|
||||
// #docregion parent-template
|
||||
`<after-content>
|
||||
<app-child></app-child>
|
||||
</after-content>`
|
||||
// #enddocregion parent-template
|
||||
+ `</div>
|
||||
|
||||
<h4>-- AfterContent Logs --</h4>
|
||||
<p><button (click)="reset()">Reset</button></p>
|
||||
<div *ngFor="let msg of logger.logs">{{msg}}</div>
|
||||
</div>
|
||||
`,
|
||||
styles: ['.parent {background: burlywood}'],
|
||||
providers: [LoggerService]
|
||||
})
|
||||
export class AfterContentParentComponent {
|
||||
show = true;
|
||||
|
||||
constructor(public logger: LoggerService) {
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.logger.clear();
|
||||
// quickly remove and reload AfterContentComponent which recreates it
|
||||
this.show = false;
|
||||
this.logger.tick_then(() => this.show = true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
import { LoggerService } from './logger.service';
|
||||
|
||||
@Component({
|
||||
selector: 'after-view-parent',
|
||||
template: `
|
||||
<div class="parent">
|
||||
<h2>AfterView</h2>
|
||||
|
||||
<after-view *ngIf="show"></after-view>
|
||||
|
||||
<h4>-- AfterView Logs --</h4>
|
||||
<p><button (click)="reset()">Reset</button></p>
|
||||
<div *ngFor="let msg of logger.logs">{{msg}}</div>
|
||||
</div>
|
||||
`,
|
||||
styles: ['.parent {background: burlywood}'],
|
||||
providers: [LoggerService]
|
||||
})
|
||||
export class AfterViewParentComponent {
|
||||
show = true;
|
||||
|
||||
constructor(public logger: LoggerService) { }
|
||||
|
||||
reset() {
|
||||
this.logger.clear();
|
||||
// quickly remove and reload AfterViewComponent which recreates it
|
||||
this.show = false;
|
||||
this.logger.tick_then(() => this.show = true);
|
||||
}
|
||||
}
|
|
@ -2,20 +2,9 @@
|
|||
// #docregion
|
||||
import { AfterViewChecked, AfterViewInit, Component, ViewChild } from '@angular/core';
|
||||
|
||||
import { ChildViewComponent } from './child-view.component';
|
||||
import { LoggerService } from './logger.service';
|
||||
|
||||
//////////////////
|
||||
// #docregion child-view
|
||||
@Component({
|
||||
selector: 'app-child-view',
|
||||
template: '<input [(ngModel)]="hero">'
|
||||
})
|
||||
export class ChildViewComponent {
|
||||
hero = 'Magneta';
|
||||
}
|
||||
// #enddocregion child-view
|
||||
|
||||
//////////////////////
|
||||
@Component({
|
||||
selector: 'after-view',
|
||||
// #docregion template
|
||||
|
@ -84,34 +73,3 @@ export class AfterViewComponent implements AfterViewChecked, AfterViewInit {
|
|||
// ...
|
||||
}
|
||||
// #enddocregion hooks
|
||||
|
||||
//////////////
|
||||
@Component({
|
||||
selector: 'after-view-parent',
|
||||
template: `
|
||||
<div class="parent">
|
||||
<h2>AfterView</h2>
|
||||
|
||||
<after-view *ngIf="show"></after-view>
|
||||
|
||||
<h4>-- AfterView Logs --</h4>
|
||||
<p><button (click)="reset()">Reset</button></p>
|
||||
<div *ngFor="let msg of logger.logs">{{msg}}</div>
|
||||
</div>
|
||||
`,
|
||||
styles: ['.parent {background: burlywood}'],
|
||||
providers: [LoggerService]
|
||||
})
|
||||
export class AfterViewParentComponent {
|
||||
show = true;
|
||||
|
||||
constructor(public logger: LoggerService) {
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.logger.clear();
|
||||
// quickly remove and reload AfterViewComponent which recreates it
|
||||
this.show = false;
|
||||
this.logger.tick_then(() => this.show = true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,32 +5,22 @@ import { FormsModule } from '@angular/forms';
|
|||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
import {
|
||||
AfterContentParentComponent,
|
||||
AfterContentComponent,
|
||||
ChildComponent
|
||||
} from './after-content.component';
|
||||
import { AfterContentParentComponent } from './after-content-parent.component';
|
||||
import { AfterContentComponent } from './after-content.component';
|
||||
import { ChildComponent } from './child.component';
|
||||
|
||||
import {
|
||||
AfterViewParentComponent,
|
||||
AfterViewComponent,
|
||||
ChildViewComponent
|
||||
} from './after-view.component';
|
||||
import { AfterViewParentComponent } from './after-view-parent.component';
|
||||
import { AfterViewComponent } from './after-view.component';
|
||||
import { ChildViewComponent } from './child-view.component';
|
||||
|
||||
import {
|
||||
CounterParentComponent,
|
||||
MyCounterComponent
|
||||
} from './counter.component';
|
||||
import { CounterParentComponent } from './counter-parent.component';
|
||||
import { MyCounterComponent } from './counter.component';
|
||||
|
||||
import {
|
||||
DoCheckParentComponent,
|
||||
DoCheckComponent
|
||||
} from './do-check.component';
|
||||
import { DoCheckParentComponent } from './do-check-parent.component';
|
||||
import { DoCheckComponent } from './do-check.component';
|
||||
|
||||
import {
|
||||
OnChangesParentComponent,
|
||||
OnChangesComponent
|
||||
} from './on-changes.component';
|
||||
import { OnChangesParentComponent } from './on-changes-parent.component';
|
||||
import { OnChangesComponent } from './on-changes.component';
|
||||
|
||||
import { PeekABooParentComponent } from './peek-a-boo-parent.component';
|
||||
import { PeekABooComponent } from './peek-a-boo.component';
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
// #docregion child-view
|
||||
@Component({
|
||||
selector: 'app-child-view',
|
||||
template: '<input [(ngModel)]="hero">'
|
||||
})
|
||||
export class ChildViewComponent {
|
||||
hero = 'Magneta';
|
||||
}
|
||||
// #enddocregion child-view
|
|
@ -0,0 +1,9 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-child',
|
||||
template: '<input [(ngModel)]="hero">'
|
||||
})
|
||||
export class ChildComponent {
|
||||
hero = 'Magneta';
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
import { LoggerService } from './logger.service';
|
||||
|
||||
@Component({
|
||||
selector: 'counter-parent',
|
||||
template: `
|
||||
<div class="parent">
|
||||
<h2>Counter Spy</h2>
|
||||
|
||||
<button (click)="updateCounter()">Update counter</button>
|
||||
<button (click)="reset()">Reset Counter</button>
|
||||
|
||||
<app-counter [counter]="value"></app-counter>
|
||||
|
||||
<h4>-- Spy Lifecycle Hook Log --</h4>
|
||||
<div *ngFor="let msg of spyLog">{{msg}}</div>
|
||||
</div>
|
||||
`,
|
||||
styles: ['.parent {background: gold;}'],
|
||||
providers: [LoggerService]
|
||||
})
|
||||
export class CounterParentComponent {
|
||||
value: number;
|
||||
spyLog: string[] = [];
|
||||
|
||||
private logger: LoggerService;
|
||||
|
||||
constructor(logger: LoggerService) {
|
||||
this.logger = logger;
|
||||
this.spyLog = logger.logs;
|
||||
this.reset();
|
||||
}
|
||||
|
||||
updateCounter() {
|
||||
this.value += 1;
|
||||
this.logger.tick();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.logger.log('-- reset --');
|
||||
this.value = 0;
|
||||
this.logger.tick();
|
||||
}
|
||||
}
|
|
@ -4,8 +4,6 @@ import {
|
|||
OnChanges, SimpleChanges,
|
||||
} from '@angular/core';
|
||||
|
||||
import { LoggerService } from './logger.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-counter',
|
||||
template: `
|
||||
|
@ -37,46 +35,3 @@ export class MyCounterComponent implements OnChanges {
|
|||
this.changeLog.push(`counter: currentValue = ${cur}, previousValue = ${prev}`);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'counter-parent',
|
||||
template: `
|
||||
<div class="parent">
|
||||
<h2>Counter Spy</h2>
|
||||
|
||||
<button (click)="updateCounter()">Update counter</button>
|
||||
<button (click)="reset()">Reset Counter</button>
|
||||
|
||||
<app-counter [counter]="value"></app-counter>
|
||||
|
||||
<h4>-- Spy Lifecycle Hook Log --</h4>
|
||||
<div *ngFor="let msg of spyLog">{{msg}}</div>
|
||||
</div>
|
||||
`,
|
||||
styles: ['.parent {background: gold;}'],
|
||||
providers: [LoggerService]
|
||||
})
|
||||
export class CounterParentComponent {
|
||||
value: number;
|
||||
spyLog: string[] = [];
|
||||
|
||||
private logger: LoggerService;
|
||||
|
||||
constructor(logger: LoggerService) {
|
||||
this.logger = logger;
|
||||
this.spyLog = logger.logs;
|
||||
this.reset();
|
||||
}
|
||||
|
||||
updateCounter() {
|
||||
this.value += 1;
|
||||
this.logger.tick();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.logger.log('-- reset --');
|
||||
this.value = 0;
|
||||
this.logger.tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import { Component, ViewChild } from '@angular/core';
|
||||
|
||||
import { DoCheckComponent } from './do-check.component';
|
||||
import { Hero } from './hero';
|
||||
|
||||
@Component({
|
||||
selector: 'do-check-parent',
|
||||
templateUrl: './do-check-parent.component.html',
|
||||
styles: ['.parent {background: Lavender}']
|
||||
})
|
||||
export class DoCheckParentComponent {
|
||||
hero: Hero;
|
||||
power: string;
|
||||
title = 'DoCheck';
|
||||
@ViewChild(DoCheckComponent) childView: DoCheckComponent;
|
||||
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.hero = new Hero('Windstorm');
|
||||
this.power = 'sing';
|
||||
if (this.childView) {
|
||||
this.childView.reset();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
/* tslint:disable:forin */
|
||||
// #docregion
|
||||
import { Component, DoCheck, Input, ViewChild } from '@angular/core';
|
||||
import { Component, DoCheck, Input } from '@angular/core';
|
||||
|
||||
class Hero {
|
||||
constructor(public name: string) {}
|
||||
}
|
||||
import { Hero } from './hero';
|
||||
|
||||
@Component({
|
||||
selector: 'do-check',
|
||||
|
@ -71,23 +69,3 @@ export class DoCheckComponent implements DoCheck {
|
|||
this.changeLog = [];
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'do-check-parent',
|
||||
templateUrl: './do-check-parent.component.html',
|
||||
styles: ['.parent {background: Lavender}']
|
||||
})
|
||||
export class DoCheckParentComponent {
|
||||
hero: Hero;
|
||||
power: string;
|
||||
title = 'DoCheck';
|
||||
@ViewChild(DoCheckComponent) childView: DoCheckComponent;
|
||||
|
||||
constructor() { this.reset(); }
|
||||
|
||||
reset() {
|
||||
this.hero = new Hero('Windstorm');
|
||||
this.power = 'sing';
|
||||
if (this.childView) { this.childView.reset(); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
export class Hero {
|
||||
constructor(public name: string) { }
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
import { Component, ViewChild } from '@angular/core';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { OnChangesComponent } from './on-changes.component';
|
||||
|
||||
@Component({
|
||||
selector: 'on-changes-parent',
|
||||
templateUrl: './on-changes-parent.component.html',
|
||||
styles: ['.parent {background: Lavender;}']
|
||||
})
|
||||
export class OnChangesParentComponent {
|
||||
hero: Hero;
|
||||
power: string;
|
||||
title = 'OnChanges';
|
||||
@ViewChild(OnChangesComponent) childView: OnChangesComponent;
|
||||
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
// new Hero object every time; triggers onChanges
|
||||
this.hero = new Hero('Windstorm');
|
||||
// setting power only triggers onChanges if this value is different
|
||||
this.power = 'sing';
|
||||
if (this.childView) {
|
||||
this.childView.reset();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,8 @@
|
|||
/* tslint:disable:forin */
|
||||
// #docregion
|
||||
import {
|
||||
Component, Input, OnChanges,
|
||||
SimpleChanges, ViewChild
|
||||
} from '@angular/core';
|
||||
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||||
|
||||
class Hero {
|
||||
constructor(public name: string) {}
|
||||
}
|
||||
import { Hero } from './hero';
|
||||
|
||||
@Component({
|
||||
selector: 'on-changes',
|
||||
|
@ -45,27 +40,3 @@ export class OnChangesComponent implements OnChanges {
|
|||
|
||||
reset() { this.changeLog = []; }
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'on-changes-parent',
|
||||
templateUrl: './on-changes-parent.component.html',
|
||||
styles: ['.parent {background: Lavender;}']
|
||||
})
|
||||
export class OnChangesParentComponent {
|
||||
hero: Hero;
|
||||
power: string;
|
||||
title = 'OnChanges';
|
||||
@ViewChild(OnChangesComponent) childView: OnChangesComponent;
|
||||
|
||||
constructor() {
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
// new Hero object every time; triggers onChanges
|
||||
this.hero = new Hero('Windstorm');
|
||||
// setting power only triggers onChanges if this value is different
|
||||
this.power = 'sing';
|
||||
if (this.childView) { this.childView.reset(); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,31 +5,17 @@ import {
|
|||
AfterContentInit,
|
||||
AfterViewChecked,
|
||||
AfterViewInit,
|
||||
Directive,
|
||||
Component,
|
||||
DoCheck,
|
||||
Input,
|
||||
OnChanges,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
SimpleChanges
|
||||
} from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
|
||||
import { LoggerService } from './logger.service';
|
||||
|
||||
let nextId = 1;
|
||||
|
||||
// #docregion ngOnInit
|
||||
@Directive()
|
||||
export class PeekABooDirective implements OnInit {
|
||||
constructor(private logger: LoggerService) { }
|
||||
|
||||
// implement OnInit's `ngOnInit` method
|
||||
ngOnInit() { this.logIt(`OnInit`); }
|
||||
|
||||
logIt(msg: string) {
|
||||
this.logger.log(`#${nextId++} ${msg}`);
|
||||
}
|
||||
}
|
||||
// #enddocregion ngOnInit
|
||||
import { PeekABooDirective } from './peek-a-boo.directive';
|
||||
|
||||
@Component({
|
||||
selector: 'peek-a-boo',
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import { Directive, OnInit } from '@angular/core';
|
||||
|
||||
import { LoggerService } from './logger.service';
|
||||
|
||||
let nextId = 1;
|
||||
|
||||
// #docregion ngOnInit
|
||||
@Directive()
|
||||
export class PeekABooDirective implements OnInit {
|
||||
constructor(private logger: LoggerService) { }
|
||||
|
||||
// implement OnInit's `ngOnInit` method
|
||||
ngOnInit() {
|
||||
this.logIt(`OnInit`);
|
||||
}
|
||||
|
||||
logIt(msg: string) {
|
||||
this.logger.log(`#${nextId++} ${msg}`);
|
||||
}
|
||||
}
|
||||
// #enddocregion ngOnInit
|
|
@ -24,7 +24,7 @@ The hooks give you the opportunity to act on a component or directive instance a
|
|||
Each interface defines the prototype for a single hook method, whose name is the interface name prefixed with `ng`.
|
||||
For example, the `OnInit` interface has a hook method named `ngOnInit()`. If you implement this method in your component or directive class, Angular calls it shortly after checking the input properties for that component or directive for the first time.
|
||||
|
||||
<code-example path="lifecycle-hooks/src/app/peek-a-boo.component.ts" region="ngOnInit" header="peek-a-boo.component.ts (excerpt)"></code-example>
|
||||
<code-example path="lifecycle-hooks/src/app/peek-a-boo.directive.ts" region="ngOnInit" header="peek-a-boo.directive.ts (excerpt)"></code-example>
|
||||
|
||||
You don't have to implement all (or any) of the lifecycle hooks, just the ones you need.
|
||||
|
||||
|
@ -464,7 +464,7 @@ The *AfterView* sample explores the `AfterViewInit()` and `AfterViewChecked()` h
|
|||
|
||||
Here's a child view that displays a hero's name in an `<input>`:
|
||||
|
||||
<code-example path="lifecycle-hooks/src/app/after-view.component.ts" region="child-view" header="ChildComponent"></code-example>
|
||||
<code-example path="lifecycle-hooks/src/app/child-view.component.ts" region="child-view" header="ChildViewComponent"></code-example>
|
||||
|
||||
The `AfterViewComponent` displays this child view *within its template*:
|
||||
|
||||
|
@ -528,7 +528,7 @@ This time, instead of including the child view within the template, it imports t
|
|||
the `AfterContentComponent`'s parent.
|
||||
The following is the parent's template.
|
||||
|
||||
<code-example path="lifecycle-hooks/src/app/after-content.component.ts" region="parent-template" header="AfterContentParentComponent (template excerpt)"></code-example>
|
||||
<code-example path="lifecycle-hooks/src/app/after-content-parent.component.ts" region="parent-template" header="AfterContentParentComponent (template excerpt)"></code-example>
|
||||
|
||||
Notice that the `<app-child>` tag is tucked between the `<after-content>` tags.
|
||||
Never put content between a component's element tags *unless you intend to project that content
|
||||
|
|
Loading…
Reference in New Issue