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:
Alexey Elin 2020-12-20 00:23:14 +03:00 committed by atscott
parent 9be9e466b1
commit aea265bfc5
17 changed files with 242 additions and 233 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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';

View File

@ -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

View File

@ -0,0 +1,9 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-child',
template: '<input [(ngModel)]="hero">'
})
export class ChildComponent {
hero = 'Magneta';
}

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}
}

View File

@ -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(); }
}
}

View File

@ -0,0 +1,3 @@
export class Hero {
constructor(public name: string) { }
}

View File

@ -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();
}
}
}

View File

@ -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(); }
}
}

View File

@ -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',

View File

@ -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

View File

@ -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