若想要直接取得目前 child componet 的值 (不是做 content projection)
那就要使用 @ViewChild
想要取得 <auth-message>
child componet 的值的話
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div > <form (ngSubmit )="onSubmit(form.value)" #form ="ngForm" > <ng-content select ="h3" > </ng-content > <label > Email address <input type ="email" name ="email" ngModel > </label > <label > Password <input type ="password" name ="password" ngModel > </label > <ng-content select ="auth-remember" > </ng-content > <auth-message [style.display ]="(showMessage ? 'inherit' : 'none')" > </auth-message > <ng-content select ="button" > </ng-content > </form > </div >
使用
1 @ViewChild(AuthMessageComponent) message: AuthMessageComponent;
取得 <auth-message>
child componet 的值
並 impplements AfterViewInit, 實作 ngAfterViewInit() 方法
在這想要直接修改 <auth-message>
component 內的 message 值
1 2 3 ngAfterViewInit() { this .message.days = 30 ; }
但卻發現會噴錯!
這個錯誤原因應該是因為
在dev模式下,額外增加了一次變化檢測,在第一輪變化檢測週期結束後,會立即進行第二輪變化檢測,對比兩次檢測值,如果不相同,則認為是變化檢測引起的。
reference by: 用 ngif 多次判斷 Expression has changed after it was checked
所以會噴這樣的錯誤
所以解決辦法是把這段移到 ngAfterContentInit()
提前修改值, 就不會噴錯了
(因為 ngAfterContentInit()
發生在 ngAfterViewInit()
之前)
1 2 3 4 5 ngAfterContentInit() { if (this .message) { this .message.days = 30 ; } }
auth-form.componet.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 import { Component, Output, ViewChild, AfterViewInit, EventEmitter, ContentChildren, QueryList, AfterContentInit } from '@angular/core' ;import { AuthRememberComponent } from './auth-remember.component' ;import { AuthMessageComponent } from './auth-message.component' ;import { User } from './auth-form.interface' ;@Component({ selector: 'auth-form' , template: ` <div> <form (ngSubmit)="onSubmit(form.value)" #form="ngForm"> <ng-content select="h3"></ng-content> <label> Email address <input type="email" name="email" ngModel> </label> <label> Password <input type="password" name="password" ngModel> </label> <ng-content select="auth-remember"></ng-content> <auth-message [style.display]="(showMessage ? 'inherit' : 'none')"> </auth-message> <ng-content select="button"></ng-content> </form> </div> ` }) export class AuthFormComponent implements AfterContentInit , AfterViewInit { showMessage: boolean; @ViewChild(AuthMessageComponent) message: AuthMessageComponent; @ContentChildren(AuthRememberComponent) remember: QueryList<AuthRememberComponent>; @Output() submitted: EventEmitter<User> = new EventEmitter<User>(); ngAfterViewInit() { } ngAfterContentInit() { if (this .message) { this .message.days = 30 ; } if (this .remember) { this .remember.forEach((item ) => { item.checked.subscribe((checked: boolean ) => this .showMessage = checked); }); } } onSubmit(value: User) { this .submitted.emit(value); } }
auth-message.component.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 import { Component } from '@angular/core' ;@Component({ selector: 'auth-message' , template: ` <div> You will be logged in for {{ days }} days </div> ` }) export class AuthMessageComponent { days: number = 7 ; }
Result
Reference