Retrieve elements created by ngFor in ngAfterViewInit

后端 未结 2 1663
青春惊慌失措
青春惊慌失措 2020-12-21 03:39

I\'m implementing a lazy image loader in my Angular (5) app, and am curious how I can avoid having to call setTimeout() in my ngAfterViewInit(), if

相关标签:
2条回答
  • 2020-12-21 04:04

    You can use the requesAnimationFrame API.

    Your problem is that even though Angular told the browser to render the images, they are not rendered yet, it takes some times for it to do so and update the DOM, that's why your array is empty.

    The requestAnimationFrame API asks for the browser to tell you (via a callback method) when it's done with it's current tasks, when rendering is complete.

    ngAfterViewInit(): void {
      window.requestAnimationFrame(() => {
        //place your code here
      })
    }
    
    0 讨论(0)
  • 2020-12-21 04:08

    This stackblitz shows one method to get notified when the elements have been created with the ngFor directive. In the template, you assign a template reference variable #lazyImage to the img element:

    <div *ngFor="let workCategory of workCategories">
      ...
      <div *ngFor="let workSample of workCategory.fields.workSamples">
        <img #lazyImage width="294" height="294" class="lazy-image" src="..." data-src="..." />
      </div>
    </div>
    

    In the code, @ViewChildren("lazyImage") is used to declare a QueryList<ElementRef> associated to these images. By subscribing to the changes event of the Querylist in ngAfterViewInit, you get notified when the elements are available. The HTML elements can then be retrieved from the QueryList:

    import { Component, ViewChildren, AfterViewInit, QueryList } from '@angular/core';
    
    @Component({
      ...
    })
    export class AppComponent {
    
      @ViewChildren("lazyImage") lazyImages: QueryList<ElementRef>;
    
      ngAfterViewInit() {
        this.lazyImages.changes.subscribe(() => {
          let images = this.lazyImages.toArray().map(x => x.nativeElement);
        });
      }
    }
    

    In cases where only the last created item is to be processed, the QueryList.last can be used:

        this.lazyImages.changes.subscribe(() => {
          this.doSomethingOnLastImage(this.lazyImages.last);
        });
    
    0 讨论(0)
提交回复
热议问题