0

In my html i have async pipe and ElementReference. In ts iam setting data comes with async pipe to nativeElement.innerHTML but iam getting this on console.

Cannot read properties of undefined (reading 'nativeElement')

Html

<div *ngIf="(article$ | async) as article">

    <div #articleBody>
    </div>

</div>

Ts

@ViewChild("articleBody") articleBody: ElementRef;

ngAfterViewInit() {
    this.article$ = this.articleService.article$.pipe(
      tap(x => {
        this.articleBody.nativeElement.innerHTML = x.body
      })
    )
  }

How can i solve this ?

wostory
  • 23
  • 7

3 Answers3

0

You need to handle this with run change detector manually. Angular will init ViewChild on ngAfterInit but you init the data in it, too. So try this

…

constructor(private changeDetector: ChangeDetectorRef) {}

ngAfterViewInit() {
    this.article$ = this.articleService.article$.pipe(
      tap(x => {
        this.changeDetector.detectChanges();
        this.articleBody.nativeElement.innerHTML = x.body
      })
    )
  }

This force Angular to check all changes. Then your ViewChild is available.

Flo
  • 2,232
  • 2
  • 11
  • 18
0

A cleaner solution than the timeout would be relying on ViewChildren and subscribing to its changes.

Something like :

@ViewChildren('articleBody', {read: ElementRef}) el: QueryList<ElementRef>;

/**
 * Listen within this component
 */
private listenForPlotChanges() {
    this.el.changes.subscribe(
        (next: QueryList<ElementRef>) => {
            // check the length if the elements has been rendered. 
         }
    );
}
Matthieu Riegler
  • 31,918
  • 20
  • 95
  • 134
0

As I mentioned just use a setTimeout around your function. This is used very commonly to avoid these types of issues.

cont t = setTimeout(()=>{
//do something
clearTimeout(t) // avoid memory leak
},1)
Judson Terrell
  • 4,204
  • 2
  • 29
  • 45