Using ElementRef with async pipe

352 Views Asked by At

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 ?

3

There are 3 best solutions below

1
Flo On

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.

0
Matthieu Riegler On

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. 
         }
    );
}
0
Judson Terrell On

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)