'Looping through Angular QueryList

So I want to get all the images in my component in an array, so I am using Angular's @ViewChildren which returns a QueryList of ElementRef:

@ViewChildren('img', { read: ElementRef }) images: QueryList<ElementRef>;

However, when ever I try to loop through the list am can't ever seem to get hold of the nativeElement. I am calling this in ngAfterViewInit()

this.images.forEach((img, index) => console.log("Image", img.nativeElement));

I don't get anything in the console.log, no error nothing.

This in turn does work:

console.log("this.images", this.images);

Below is an image of the log of console.log("this.images", this.images):

enter image description here

Here the html:

<div class="swiper-slide" *ngFor="let exhibit of exhibits; let i = index">
   <app-exhibit-images exhibitImagesId="{{ exhibit.fields.eventImages[0].sys.id }}" [eventPicturesStart]="eventPicturesStart" (sendEndEventPictures)="getEndEventImages($event)"></app-exhibit-images>
   <div id="exhibit-{{i}}"class="gallery__content" [ngClass]="{'show-event-pictures' : eventPicturesStart}">
      <div class="gallery__poster" [ngClass]="{'gallery-expand' : isGalleryExpanded }">
         <figure class="poster__image">
            <picture>
               <source srcset="{{ exhibit.fields.photo.fields.file.url }}" type="img/png">
               <img #img src="{{ exhibit.fields.photo.fields.file.url }}" alt="{{ exhibit.fields.photo.fields.description }}">
            </picture>
         </figure>
      </div>
      <div class="gallery__text" [ngClass]="{'gallery-expand' : isGalleryExpanded }">
         <button class="gallery-expand-button" (click)="expandGallery()"></button>
         <h2 class="gallery__heading">{{ exhibit.fields.title }}</h2>
         <h3 class="gallery__subheading">{{ exhibit.fields.subTitle }}</h3>
         <h4 class="gallery__artist">{{ exhibit.fields.artist }}</h4>
         <p class="gallery__description" *ngIf="exhibit.fields.description">{{ exhibit.fields.description }}</p>
      </div>
   </div>
</div>

What am I missing?



Solution 1:[1]

I ran into a similar issue with @ContentChildren. The solution was to subscribe to the changes observable of the QueryList.

Essentially, this will trigger whenever any of the state of the children changes. Normally this wouldn't be necessary but if your list of children is loaded in via a GET, this ensures the QueryList is data is loaded before executing on it. Its important to note the subscription will fire again whenever the any of the children's content changes.

@ContentChildren(forwardRef(() => ChildComponent), { descendants: true })
private children: QueryList<ChildComponent>;

ngAfterContentInit() {
    // subscribe to changes
    this.children.changes.subscribe(children => {
        children.forEach(child => {
            // do something with each child...
        });
    });
}

Solution 2:[2]

Don't call your loop in ngAfterViewInit, use ngAfterViewChecked instead. This will be triggered AFTER your child components are checked.

See lifecycle-hooks

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jrswgtr
Solution 2 A. Sa.