0

In my Angular 14 App I've got component with canvas in template. Whole template is under *ngIf checking if data was emitted by Observable. I need to create Chart using data from Observable and canvas reference which I get with @ViewChild. The problem is, when I got data in Observable pipe, canvas element is not rendered yet. I can use setTimeout in Observable pipe and it will work but I don't want to use it, so I've been looking for better solution and finally I've come up with one below.

1 I've got canvas @ViewChild, BehaviorSubject canvasLoaded$ with initial value false, and canvasLoadedSubscription:

@ViewChild('canvas') canvas!: ElementRef;
 canvasLoaded$: BehaviorSubject<boolean> = new BehaviorSubject(false);
 canvasLoadedSubscription!: Subscription;

2 I've got method subscribeToCanvasLoaded where I subscribe to canvasLoaded$ saving subscription in canvasLoadedSubscription, and call renderCharts if canvasLoaded$ emits true:

subscribeToCanvasLoaded(data: any): void {
    this.canvasLoadedSubscription = this.canvasLoaded$
    .pipe(filter(Boolean))
    .subscribe(() => this.renderCharts(data));
  }

3 in data$ pipe I call subscribeToCanvasLoaded method passing data:

this.data$ = this.dataService.data$.pipe(
      filter(Boolean),
      tap((data) => { 
        if(data.length) {
          this.subscribeToCanvasLoaded(data)
        }
      })
    );

4 in ngAfterContentChecked if I already can access canvas and if canvasLoaded$ still false I set it to true and unsubscribe from canvasLoadedSubscription:

ngAfterContentChecked(): void {
    if(this.canvas && !this.canvasLoaded$.value) {
      this.canvasLoaded$.next(true);
      this.canvasLoadedSubscription.unsubscribe();
    }
  }

this way I don't have to save data in component, it goes straight to template where I use async pipe, I don't have to use seTimeout() and I know for sure when canvas is in DOM.

Are there any better solutions for my problem?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.