[Angular] ViewChild遇上ngIf
當我們有一個child component想要用ViewChild的方法在parent component取得物件,但如果在上面加上ngIf的時候,取得物件的這個動作就會發現根本取不到!!!
在app.component中,使用todo.component,並且加上ngIf作為控制是否顯示
| 1 | <button (click)="setFlag(!flag)">toggle flag</button> | 
在component中,使用ViewChild的方法並且在setFlag中印出物件,就可以發現在這個時候是取不到todo這個物件的,就算是用angularJS常用的setTimeout也是一樣
這個問題應該就是變數還沒反應到html,所以導致根本還沒拿到這個物件
| 1 | export class AppComponent { | 
解決方案
但這樣根本不能拿到物件要怎麼往後處理,那這邊有兩個作法
- 在child component使用事件作為觸發,當物件被ngIf啟動後,就可以拋出事件 - 1 
 2
 3
 4
 5
 6
 7- export class TodoComponent implements AfterViewInit { 
 () onInit = new EventEmitter();
 ngAfterViewInit() {
 this.onInit.emit(this);
 }
 }- 在parent component收到事件後再去操作ViewChild的物件,就可以正常使用 - 1 
 2
 3
 4- <button (click)="setFlag(!flag)">toggle flag</button> 
 <app-todo (onInit)="trigerTodo($event)" *ngIf="flag">
 </app-todo>- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- export class AppComponent { 
 (TodoComponent) todo: TodoComponent;
 setFlag(flag) {
 this.flag = flag;
 }
 trigerTodo(event) {
 console.log('component', event);
 }
 }
- ViewChild使用setter,當物件被建立時,就可以在裡面進行操作 - 1 
 2
 3
 4
 5
 6
 7
 8
 9- export class AppComponent { 
 (TodoComponent) set todo(content: ViewContainerRef) {
 console.log('setter', content);
 }
 setFlag(flag) {
 this.flag = flag;
 }
 }
結論
其實在使用ViewChild的時候,使用ngIf其實是不好的應用,但如果真的要用就必須要繞路一下,也要去了解一下各種使用方法,上面的兩個方法,我個人比較喜歡setter的作法,簡單乾淨!
如果有其他作法或想法歡迎來討論喔!!