Home  >  Angular 4

Angular 2/4 QueryList Example

By Arvind Rai, September 21, 2017
This page will walk through Angular QueryList example. QueryList is unmodifiable list of items that Angular keeps up to date when the state of the application changes. 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. QueryList can contain the elements of the type directive, component, ElementRef, any etc. Here we will create a complete example for 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 map, filter, find, forEach 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> 
Now let us discuss the complete example step by step.

Technologies Used

Find the technologies being used in our example.
1. Angular 4.2.4
2. TypeScript 2.3.3
3. Node.js 6.10.1
4. Angular CLI 1.3.1
5. Angular Compiler CLI 4.2.4

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 of QueryList 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 iterate QueryList, 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 in QueryList, 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));	
}); 
In the 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 a QueryList, 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 a QueryList, 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 of QueryList 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: QueryList<MessageDirective> 

    @ViewChild('msgTemp')
    private msgTempRef : TemplateRef<any>	
	
    //QueryList + @ViewChildren + Component
    @ViewChildren('bkWriter') 
    allWriters: QueryList<WriterComponent>	
	
    showAllWriter = false;
	
    //QueryList + @ViewChildren + ElementRef
    @ViewChildren('pname') 
    allPersons: QueryList<ElementRef>	
	
    ngAfterViewInit() {
	console.log('--- using QueryList.changes ---');		
	this.allWriters.changes.subscribe(list => {
             list.forEach(writer => 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;
    }	
} 
cp1.component.html
<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> 
writer.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'writer',
  template: `
       {{writerName}} - {{bookName}}
  `
})
export class WriterComponent {
   @Input('name') writerName: string;
   @Input('book') bookName: string;
} 
message.directive.ts
import { Directive, ViewContainerRef } from '@angular/core';

@Directive({ 
   selector: '[cpMsg]' 
})
export class MessageDirective {
   constructor(public viewContainerRef: ViewContainerRef) { }
} 

QueryList + @ContentChildren Example

Find the example of QueryList 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;
   }     
} 
cp2.component.html
<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> 
book.directive.ts
import { Directive, Input } from '@angular/core';

@Directive({
    selector: 'book'
})
export class BookDirective {
    @Input() bookId: string;
    @Input() bookName: string;
} 
favourite-books.component.ts
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: QueryList<BookDirective>
	
        @ContentChildren(BookDirective, {descendants: true}) 
	allBooks: QueryList<BookDirective>
	
	ngAfterContentInit() {
	   console.log('---Book details---');	
	   this.topBooks.forEach(book => console.log(book.bookId + " - " + book.bookName));	
	}
} 
favourite-friends.component.ts
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: QueryList<ElementRef>
	
	get allFriends(): string {
	   return this.allFriendsRef ? this.allFriendsRef.map(f =>f.nativeElement.innerHTML).join(', ') : '';
	}
	ngAfterContentInit() {
	   console.log(this.allFriends);
	}	
} 
app.component.ts
import { Component } from '@angular/core';

@Component({
   selector: 'app-root',
   template: `
       <app-cp1></app-cp1>
       <app-cp2></app-cp2>
   `
})
export class AppComponent { 
} 
app.module.ts
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 application, find 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
Find the print screen of the output.
Angular 2/4 QueryList Example

References

QueryList
Angular 2/4 @ContentChild and @ContentChildren Example
Angular 4 <ng-template> Example

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
FIND MORE TUTORILAS








Copyright ©2017 concretepage.com, all rights reserved |Privacy Policy | Contact Us