Angular @ContentChild and @ContentChildren
February 11, 2024
This page will walk through Angular @ContentChild
and @ContentChildren
decorator example. They are used to fetch first or all elements from content DOM. The @ContentChild
gives first element matching the selector from the content DOM. The @ContentChildren
gives all elements of content DOM as QueryList
. Contents queried by @ContentChild
and @ContentChildren
are set before ngAfterContentInit()
is called. If we perform any change in content DOM for the matching selector, that will be observed by @ContentChild
and @ContentChildren
and we will get updated value. As a selector for @ContentChild
and @ContentChildren
, we can pass directive, component or local template variable. By default @ContentChildren
only selects direct children of content DOM and not all descendants. The metadata of @ContentChildren
is descendants
and by setting its value true, we can fetch all descendant elements. Here on this page we will provide @ContentChild
and @ContentChildren
example using directive, component and ElementRef
. Now find the complete example step-by-step.
Contents
- @ContentChild and @ContentChildren
- Using AfterContentInit
- Example 1: @ContentChild and @ContentChildren using Directive
- Example 2: @ContentChild and @ContentChildren using Component
- Example 3: @ContentChild and @ContentChildren using ElementRef
- Other Components and Application Module used in Example
- References
- Download Source Code
@ContentChild and @ContentChildren
The@ContentChild
and @ContentChildren
decorators are used to fetch single child element or all child elements from content DOM. Let us understand more about it.
@ContentChild
@ContentChild
gives the first element or directive matching the selector from the content DOM. If new child element replaces the old one matching the selector in content DOM, then property will also be updated. @ContentChild
has following metadata properties.
selector: Directive type or the name used for querying. Find the example when type is directive.
@ContentChild(BookDirective) book: BookDirective;
@ContentChildren
@ContentChildren
is used to get QueryList
of elements or directives from the content DOM. When there is change in content DOM, data in QueryList
will also change. If child elements are added, we will get those new elements in QueryList
. If child elements are removed, then those elements will be removed from the QueryList
. The metadata properties of @ContentChildren
are as follows.
selector: Directive type or the name used for querying. Find the example when type is directive.
@ContentChildren(BookDirective) topBooks: QueryList<BookDirective>;
descendants
is used as follows.
@ContentChildren(BookDirective, {descendants: true}) allBooks: QueryList<BookDirective>;
descendants
is false.
read: This is optional metadata. It reads a different token from the queried element.
Using AfterContentInit
AfterContentInit
is a lifecycle hook that is called after directive content is fully initialized. It has a method ngAfterContentInit()
. This method runs after angular loads external content into the component view. This method runs once after first ngDoCheck()
method. Contents queried by @ContentChild
and @ContentChildren
are set before ngAfterContentInit()
is called. AfterContentInit
is used as given below.
@Component({ selector: 'friend', template: `` }) export class FriendComponent implements AfterContentInit { @ContentChild('name') nameRef: ElementRef; ngAfterContentInit() { console.log(this.nameRef.nativeElement.innerHTML); } }
Example 1: @ContentChild and @ContentChildren using Directive
Find the example of@ContentChild
and @ContentChildren
decorators using directive. First we will create a directive with selector as element name.
book.directive.ts
import { Directive, Input } from '@angular/core'; @Directive({ selector: 'book' }) export class BookDirective { @Input() bookId: string = ''; @Input() bookName: string = ''; }
@Input()
properties. <book>
element can be used in any component. Now create a component to use @ContentChild
decorator to query element of type <book>
.
writer.component.ts
import { Component, ContentChild } from '@angular/core'; import { BookDirective } from './book.directive'; @Component({ selector: 'writer', template: ` Name: {{writerName}} <br/>Latest Book: {{book?.bookId}} - {{book?.bookName}} ` }) export class WriterComponent { @ContentChild(BookDirective) book = {} as BookDirective; writerName = 'Mahesh'; }
person.component.html
to use <writer>
and <book>
elements.
<writer> <book bookId="1" bookName="Java 8 Tutorials" *ngIf="latestBook"></book> <book bookId="2" bookName="Learning Angular 4" *ngIf="!latestBook"></book> </writer> <br/><button (click)="onChangeBook()">Change Book</button>
person.component.ts
.
latestBook = true; onChangeBook() { this.latestBook = (this.latestBook === true)? false : true; }
@ContentChildren
using directive.
favourite-books.component.ts
import { Component, ContentChildren, QueryList } 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 { @ContentChildren(BookDirective) topBooks = {} as QueryList<BookDirective>; @ContentChildren(BookDirective, { descendants: true }) allBooks = {} as QueryList<BookDirective>; }
@ContentChildren
two times, one with default descendants
and second with descendants
with true value. Find the code snippet of person.component.html
to use <favourite-books>
and <book>
elements.
<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>
person.component.ts
.
showAllBook = false; onShowAllBooks() { this.showAllBook = (this.showAllBook === true)? false : true; }
@ContentChild
and @ContentChildren
decorators using directive.
Example 2: @ContentChild and @ContentChildren using Component
Find the example of@ContentChild
and @ContentChildren
decorators using component. Here for child element we will create a component instead of directive.
city.component.ts
import { Component, Input } from '@angular/core'; @Component({ selector: 'city', template: `` }) export class CityComponent { @Input() cityId: string = ''; @Input() cityName: string = ''; }
@Input()
properties. Now find the component that will use @ContentChild
.
address.component.ts
import { Component, ContentChild } from '@angular/core'; import { CityComponent } from './city.component'; @Component({ selector: 'address', template: ` <b>{{title}}</b> <br/>City: {{city?.cityId}} - {{city?.cityName}} ` }) export class AddressComponent { @ContentChild(CityComponent) city = {} as CityComponent; title = 'Address'; }
person.component.html
to use <address>
and <city>
element.
<address> <city cityId="1" cityName="Varanasi" *ngIf="homeTown"></city> <city cityId="2" cityName="Noida" *ngIf="!homeTown"></city> </address> <br/><button (click)="onChangeCity()">Change City</button>
person.component.ts
.
homeTown = true; onChangeCity() { this.homeTown = (this.homeTown === true)? false : true; }
@ContentChildren
using component.
favourite-cities.component.ts
import { Component, ContentChildren, QueryList } from '@angular/core'; import { CityComponent } from './city.component'; @Component({ selector: 'favourite-cities', template: ` <b>Top Favourite Cities</b> <ng-template ngFor let-city [ngForOf]= "topCities"> <br/>{{city.cityId}} - {{city.cityName}} </ng-template> <br/><b>All Favourite Cities</b> <ng-template ngFor let-city [ngForOf]= "allCities"> <br/>{{city.cityId}} - {{city.cityName}} </ng-template> ` }) export class FavouriteCitiesComponent { @ContentChildren(CityComponent) topCities = {} as QueryList<CityComponent>; @ContentChildren(CityComponent, { descendants: true }) allCities = {} as QueryList<CityComponent>; }
person.component.html
to use <favourite-cities>
and <city>
element.
<favourite-cities> <city cityId="1" cityName="Noida"></city> <city cityId="2" cityName="Mumbai"></city> <favourite-cities> <city cityId="3" cityName="Gurugram"></city> </favourite-cities> <favourite-cities *ngIf="showAllCity"> <city cityId="4" cityName="New Delhi"></city> <city cityId="5" cityName="Bengaluru"></city> </favourite-cities> </favourite-cities> <br/><button (click)="onShowAllCities()" > <label *ngIf="!showAllCity">Show More</label> <label *ngIf="showAllCity">Show Less</label> </button>
person.component.ts
.
showAllCity = false; onShowAllCities() { this.showAllCity = (this.showAllCity === true)? false : true; }
@ContentChild
and @ContentChildren
decorators using component.
Example 3: @ContentChild and @ContentChildren using ElementRef
Find the example of@ContentChild
and @ContentChildren
decorators using ElementRef
. First find the component that will use @ContentChild
with ElementRef
.
friend.component.ts
import { Component, ContentChild, ElementRef, AfterContentInit } from '@angular/core'; @Component({ selector: 'friend', template: ` Friend Name: {{friendName}} ` }) export class FriendComponent implements AfterContentInit { @ContentChild('name') nameRef = {} as ElementRef; get friendName(): String { return this.nameRef.nativeElement.innerHTML; } ngAfterContentInit() { console.log(this.friendName); } }
@ContentChild('name')
is the local template variable of a HTML element. Find the code snippet of person.component.html
to use <friend>
with a <div>
element.
<friend> <div #name *ngIf="bestFriend">Mahesh</div> <div #name *ngIf="!bestFriend">Krishna</div> </friend> <br/><button (click)="onChangeFriend()">Change Friend</button>
person.component.ts
.
bestFriend = true; onChangeFriend() { this.bestFriend = (this.bestFriend === true)? false : true; }
@ContentChildren
with ElementRef
.
favourite-friends.component.ts
import { Component, ContentChildren, QueryList, ElementRef, AfterContentInit } from '@angular/core'; @Component({ selector: 'favourite-friends', template: ` <b>All Favourite Friends</b> <br/> {{allFriends}} ` }) export class FavouriteFriendsComponent implements AfterContentInit { @ContentChildren('name') allFriendsRef = {} as QueryList<ElementRef>; get allFriends(): string { return this.allFriendsRef ? this.allFriendsRef.map(f => f.nativeElement.innerHTML).join(', ') : ''; } ngAfterContentInit() { console.log(this.allFriends); } }
@ContentChildren('name')
is the local template variable of a HTML element. Find the code snippet of person.component.html
to use <favourite-friends>
with <div>
element.
<favourite-friends> <div #name>Mohit</div> <div #name>Anup</div> <div #name *ngIf="showAllFriend">Nilesh</div> <div #name *ngIf="showAllFriend">Sravan</div> </favourite-friends> <br/><button (click)="onShowAllFriends()" > <label *ngIf="!showAllFriend">Show More</label> <label *ngIf="showAllFriend">Show Less</label> </button>
person.component.ts
.
showAllFriend = false; onShowAllFriends() { this.showAllFriend = (this.showAllFriend === true)? false : true; }
@ContentChild
and @ContentChildren
decorators using ElementRef
.
Other Components and Application Module used in Example
person.component.tsimport { Component } from '@angular/core'; @Component({ selector: 'person-app', templateUrl: './person.component.html' }) export class PersonComponent { latestBook = true; showAllBook = false; homeTown = true; showAllCity = false; bestFriend = true; showAllFriend = false; onChangeBook() { this.latestBook = (this.latestBook === true)? false : true; } onShowAllBooks() { this.showAllBook = (this.showAllBook === true)? false : true; } onChangeCity() { this.homeTown = (this.homeTown === true)? false : true; } onShowAllCities() { this.showAllCity = (this.showAllCity === true)? false : true; } onChangeFriend() { this.bestFriend = (this.bestFriend === true)? false : true; } onShowAllFriends() { this.showAllFriend = (this.showAllFriend === true)? false : true; } }
<h3>ContentChild using Directive</h3> <writer> <book bookId="1" bookName="Java 8 Tutorials" *ngIf="latestBook"></book> <book bookId="2" bookName="Learning Angular 4" *ngIf="!latestBook"></book> </writer> <br/><button (click)="onChangeBook()">Change Book</button> <h3>ContentChildren using 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>ContentChild using Component</h3> <address> <city cityId="1" cityName="Varanasi" *ngIf="homeTown"></city> <city cityId="2" cityName="Noida" *ngIf="!homeTown"></city> </address> <br/><button (click)="onChangeCity()">Change City</button> <h3>ContentChildren using Component</h3> <favourite-cities> <city cityId="1" cityName="Noida"></city> <city cityId="2" cityName="Mumbai"></city> <favourite-cities> <city cityId="3" cityName="Gurugram"></city> </favourite-cities> <favourite-cities *ngIf="showAllCity"> <city cityId="4" cityName="New Delhi"></city> <city cityId="5" cityName="Bengaluru"></city> </favourite-cities> </favourite-cities> <br/><button (click)="onShowAllCities()" > <label *ngIf="!showAllCity">Show More</label> <label *ngIf="showAllCity">Show Less</label> </button> <h3>ContentChild using ElementRef</h3> <friend> <div #name *ngIf="bestFriend">Mahesh</div> <div #name *ngIf="!bestFriend">Krishna</div> </friend> <br/><button (click)="onChangeFriend()">Change Friend</button> <h3>ContentChildren using ElementRef</h3> <favourite-friends> <div #name>Mohit</div> <div #name>Anup</div> <div #name *ngIf="showAllFriend">Nilesh</div> <div #name *ngIf="showAllFriend">Sravan</div> </favourite-friends> <br/><button (click)="onShowAllFriends()" > <label *ngIf="!showAllFriend">Show More</label> <label *ngIf="showAllFriend">Show Less</label> </button>
References
ContentChildContentChildren