@Viewchild not initializing during ngOnInit @Viewchild not initializing during ngOnInit angular angular

@Viewchild not initializing during ngOnInit


From official docs: https://angular.io/api/core/ViewChild#description

View queries are set before the ngAfterViewInit callback is called.

In order to get @ViewChild property inited, you need to call it in ngAfterViewInit lifecycle hook.

export class MessageComponent implements OnInit, AfterViewInit {   @ViewChild(MatSort) sort: MatSort;   ngAfterViewInit(){      console.log(this.sort)   }}

If you are using Angular 8, you need to refactor the implementation of @ViewChild properties since static flag is required


the problem in FeedComponent is that you are making this.dataSource.sort = this.sort assignment before initializing this.dataSource

refreshPosts(){  console.log(this.sort) < -------comes back undefined  this.posts.subscribe(posts=>{     this.postData = posts.filter(post => post.uid != `${this.currentUser.uid}` && post.claimedBy !=`${this.currentUser.uid}`);     this.dataSource= new MatTableDataSource(this.postData)     this.dataSource.sort = this.sort // make assignment after initializing this.dataSource     this.dataSource.paginator = this.paginator;    });  }

please note that console.log(this.sort) will still print undefined because of lifecycle sequences. on ngOnInit view queries are not set.

so the question arises; then how would this.dataSource.sort = this.sort assignment work in ngOnInit in MessageComponent ?

the answer is long but to put it in simple terms; because that code gets executed in subscribe callback. since the code in subscribe callback gets executed when observable emits, an asynchronous operation happens. and that async operation happens in a subsequent change detection cycle after a cycle where ngAfterViewInit hook gets executed.

you are not getting undefined output in your second component because that console.log statement is also executed in a subscribe callback. moving that log statement out of subscribe callback will also print undefined.

if you place console.log statements in ngAfterViewInit hook, they both will print actual values whether they are placed in a subscribe callback or not.

as a summary;

make assignment after initializing this.datasource

this.dataSource= new MatTableDataSource(this.postData)this.dataSource.sort = this.sort // make assignment after initializing 

and do it in ngAfterViewInit hook, even though it works in ngOnInit due to the async operation.