Angular QueryList Example
October 04, 2021
This page will walk through Angular QueryList
example. The QueryList
is unmodifiable list of items that Angular keeps up-to-date when the state of the application changes. The ViewChildren
and ContentChildren
uses QueryList
to store elements or directives from view DOM and content DOM respectively. We can subscribe to the changes of QueryList
to get the current state of QueryList
. It provides methods such as map
, filter
, find
, forEach
etc. The QueryList
can contain the elements of the type directive, component, ElementRef
, any
etc.
QueryList
is used with @ViewChildren
as given below.
@ViewChildren('bkWriter') allWriters: QueryList<WriterComponent>;
QueryList
is used with @ContentChildren
as given below.
@ContentChildren(BookDirective) topBooks: QueryList<BookDirective>;
QueryList
. We will use QueryList
with ViewChildren
and ContentChildren
in our example. We will show how to subscribe the changes of QueryList
. We will also provide how to use QueryList
methods with examples. Now let us discuss the complete example step-by-step.
Contents
Technologies Used
Find the technologies being used in our example.1. Angular 12.1.0
2. Node.js 12.14.1
3. NPM 7.20.3
Project Structure
Find the project structure of our demo application.angular-demo | |--src | | | |--app | | | | | |--cp1.component.ts | | |--cp1.component.html | | |--writer.component.ts | | |--message.directive.ts | | |--cp2.component.ts | | |--cp2.component.html | | |--book.directive.ts | | |--favourite-books.component.ts | | |--favourite-friends.component.ts | | | | | |--app.module.ts | | |--app.component.ts | | | |--main.ts | |--index.html | |--styles.css | |--node_modules |--package.json
QueryList: length, first, last
We can get the length ofQueryList
of current state, first element and last element as following.
@ViewChildren('bkWriter') allWriters: QueryList<WriterComponent>; let len = this.allWriters.length; let firstEl = this.allWriters.first; let lastEl = this.allWriters.last;
QueryList.forEach
To iterateQueryList
, it provides forEach()
method.
@ViewChildren('bkWriter') allWriters: QueryList<WriterComponent>; this.allWriters.forEach(writer => console.log(writer.writerName + ' - ' + writer.bookName));
QueryList.changes
To listen the changes inQueryList
, we can subscribe to its changes. QueryList
provides changes
getter property that returns the instance of Observable
.
@ViewChildren('bkWriter') allWriters: QueryList<WriterComponent>; this.allWriters.changes.subscribe(list => { list.forEach(writer => console.log(writer.writerName + ' - ' + writer.bookName)); });
list
we will get current state of QueryList
at any time.
QueryList.find
To find an element with a specific value,QueryList
provides find
method that returns the matching object.
@ViewChildren('bkWriter') allWriters: QueryList<WriterComponent>; let javaWriter = this.allWriters.find(writer => writer.bookName === 'Java Tutorials');
QueryList.map
To map the elements of aQueryList
, it provides map
method that returns an array of mapped elements.
@ViewChildren('bkWriter') allWriters: QueryList<WriterComponent>; let wnames = this.allWriters.map(writer => writer.writerName);
QueryList.filter
To filter aQueryList
, it provides filter
method that returns an array of elements matching the filter condition.
@ViewChildren('bkWriter') allWriters: QueryList<WriterComponent>; let writers = this.allWriters.filter(writer => writer.writerName === 'Krishna');
QueryList + @ViewChildren Example
Find the example ofQueryList
with @ViewChildren
decorator.
@ViewChildren('bkWriter') allWriters: QueryList<WriterComponent>;
@ViewChildren
gets the list of elements or directives from the view DOM as QueryList
.
cp1.component.ts
import { Component, ViewChild, ViewChildren, AfterViewInit, TemplateRef, ViewContainerRef, QueryList, ElementRef } from '@angular/core'; import { MessageDirective } from './message.directive'; import { WriterComponent } from './writer.component'; @Component({ selector: 'app-cp1', templateUrl: './cp1.component.html' }) export class Cp1Component implements AfterViewInit { //QueryList + @ViewChildren + Directive @ViewChildren(MessageDirective) private msgList = {} as QueryList<MessageDirective>; @ViewChild('msgTemp') private msgTempRef = {} as TemplateRef<any>; //QueryList + @ViewChildren + Component @ViewChildren('bkWriter') allWriters = {} as QueryList<WriterComponent>; showAllWriter = false; //QueryList + @ViewChildren + ElementRef @ViewChildren('pname') allPersons = {} as QueryList<ElementRef>; ngAfterViewInit() { console.log('--- using QueryList.changes ---'); this.allWriters.changes.subscribe(list => { list.forEach((writer: WriterComponent) => console.log(writer.writerName + ' - ' + writer.bookName)); }); console.log('--- using QueryList.forEach ---'); this.msgList.forEach(messageDirective => messageDirective.viewContainerRef.createEmbeddedView(this.msgTempRef)); this.allWriters.forEach(writer => console.log(writer.writerName + ' - ' + writer.bookName)); console.log('--- using QueryList.length ---'); console.log(this.allWriters.length); console.log('--- using QueryList.find ---'); let javaWriter = this.allWriters.find(writer => writer.bookName === 'Java Tutorials'); console.log(javaWriter?.writerName); console.log('--- using QueryList.map ---'); let wnames = this.allWriters.map(writer => writer.writerName); for (let name of wnames) { console.log(name); } console.log('--- using QueryList.filter ---'); let writers = this.allWriters.filter(writer => writer.writerName === 'Krishna'); for (let w of writers) { console.log(w.bookName); } console.log('--- using QueryList.first ---'); let firstEl = this.allPersons.first; console.log(firstEl.nativeElement.innerHTML); console.log('--- using QueryList.last ---'); let lastEl = this.allPersons.last; console.log(lastEl.nativeElement.innerHTML); } onShowAllWriters() { this.showAllWriter = (this.showAllWriter === true) ? false : true; } }
<h3>QueryList + @ViewChildren + Directive</h3> <ng-template #msgTemp> Welcome to you.<br/> Happy learning! </ng-template> <div cpMsg> </div> <div cpMsg> </div> <h3>QueryList + @ViewChildren + ElementRef</h3> <div> <div #pname>Mohit</div> <div #pname>Anup</div> <div #pname>Nilesh</div> </div> <h3>QueryList + @ViewChildren + Component</h3> <div> <writer name="Krishna" book="Angular Tutorials" #bkWriter></writer> <br/> <writer name="Mahesh" book="Java Tutorials" #bkWriter></writer> <br/> <writer name="Krishna" book="jQuery Tutorials" #bkWriter></writer> <br/> <writer name="Bramha" book="Hibernate Tutorials" #bkWriter *ngIf="showAllWriter"></writer> <br/> <writer name="Vishnu" book="Spring Tutorials" #bkWriter *ngIf="showAllWriter"></writer> </div> <button (click)="onShowAllWriters()" > <label *ngIf="!showAllWriter">Show More</label> <label *ngIf="showAllWriter">Show Less</label> </button>
import { Component, Input } from '@angular/core'; @Component({ selector: 'writer', template: ` {{writerName}} - {{bookName}} ` }) export class WriterComponent { @Input('name') writerName = ''; @Input('book') bookName = ''; }
import { Directive, ViewContainerRef } from '@angular/core'; @Directive({ selector: '[cpMsg]' }) export class MessageDirective { constructor(public viewContainerRef: ViewContainerRef) { } }
QueryList + @ContentChildren Example
Find the example ofQueryList
with @ContentChildren
decorator.
@ContentChildren(BookDirective) topBooks: QueryList<BookDirective>;
@ContentChildren
gets the list of elements or directives from the content DOM as QueryList
.
cp2.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-cp2', templateUrl: './cp2.component.html' }) export class Cp2Component { showAllBook = false; onShowAllBooks() { this.showAllBook = (this.showAllBook === true)? false : true; } }
<h3>QueryList + @ContentChildren + Directive</h3> <favourite-books> <book bookId="1" bookName="Hibernate 4 Tutorials"></book> <book bookId="2" bookName="Spring Boot Tutorials"></book> <favourite-books> <book bookId="3" bookName="Learning JavaScript"></book> </favourite-books> <favourite-books *ngIf="showAllBook"> <book bookId="4" bookName="Thymeleaf Tutorials"></book> <book bookId="5" bookName="Android Tutorials"></book> </favourite-books> </favourite-books> <br/> <button (click)="onShowAllBooks()" > <label *ngIf="!showAllBook">Show More</label> <label *ngIf="showAllBook">Show Less</label> </button> <h3>QueryList + @ContentChildren + ElementRef</h3> <favourite-friends> <div #ffname>Mohit</div> <div #ffname>Anup</div> <div #ffname>Nilesh</div> </favourite-friends>
import { Directive, Input } from '@angular/core'; @Directive({ selector: 'book' }) export class BookDirective { @Input() bookId = ''; @Input() bookName = ''; }
import { Component, ContentChildren, QueryList, AfterContentInit } from '@angular/core'; import { BookDirective } from './book.directive'; @Component({ selector: 'favourite-books', template: ` <b>Top Favourite Books</b> <ng-template ngFor let-book [ngForOf]= "topBooks"> <br/>{{book.bookId}} - {{book.bookName}} </ng-template> <br/><b>All Favorite Books</b> <ng-template ngFor let-book [ngForOf]= "allBooks"> <br/>{{book.bookId}} - {{book.bookName}} </ng-template> ` }) export class FavouriteBooksComponent implements AfterContentInit { //QueryList + @ContentChildren + Directive @ContentChildren(BookDirective) topBooks = {} as QueryList<BookDirective>; @ContentChildren(BookDirective, { descendants: true }) allBooks = {} as QueryList<BookDirective>; ngAfterContentInit() { console.log('---Book details---'); this.topBooks.forEach(book => console.log(book.bookId + " - " + book.bookName)); } }
import { Component, ContentChildren, QueryList, ElementRef, AfterContentInit } from '@angular/core'; @Component({ selector: 'favourite-friends', template: ` {{allFriends}} ` }) export class FavouriteFriendsComponent implements AfterContentInit { //QueryList + @ContentChildren + ElementRef @ContentChildren('ffname') allFriendsRef = {} as QueryList<ElementRef>; get allFriends(): string { return this.allFriendsRef ? this.allFriendsRef.map(f => f.nativeElement.innerHTML).join(', ') : ''; } ngAfterContentInit() { console.log(this.allFriends); } }
import { Component } from '@angular/core'; @Component({ selector: 'app-root', template: ` <app-cp1></app-cp1> <app-cp2></app-cp2> ` }) export class AppComponent { }
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { AppComponent } from './app.component'; import { Cp1Component } from './cp1.component'; import { WriterComponent } from './writer.component'; import { MessageDirective } from './message.directive'; import { BookDirective } from './book.directive'; import { FavouriteBooksComponent } from './favourite-books.component'; import { FavouriteFriendsComponent } from './favourite-friends.component'; import { Cp2Component } from './cp2.component'; @NgModule({ imports: [ BrowserModule ], declarations: [ AppComponent, Cp1Component, WriterComponent, MessageDirective, BookDirective, FavouriteBooksComponent, FavouriteFriendsComponent, Cp2Component ], providers: [ ], bootstrap: [ AppComponent ] }) export class AppModule { }
Run Application
To run the demo application, find the following steps.1. Download source code using download link given below on this page.
2. Use downloaded src in your angular CLI application. To install angular CLI, find the link.
3. Run ng serve using command prompt.
4. Now access the URL http://localhost:4200

References
QueryListAngular @ContentChild and @ContentChildren Example
Angular <ng-template> Example