Angular component ContentChild or ContentChildren can be defined as first or all child elements which are projected into given component from the parent component. Therefore, they refer to elements from components content DOM. They include only elements found within <ng-content></ng-content>. The initialization of these decorators when Angular lifecycle phase "AfterContentInit" runs.
@ContentChild and @ContentChildren Decorator
ContentChild searches the selector within content DOM elements which are projected from parent component to child component and returns first element matching selector. ContentChildren is similar to ContentChild only it returns QueryList of child elements matching selector from content DOM. The selector can be a Directive, Component or local template variable.
@ContentChild has following metadata properties
- selector : It refers to type of Directive or name used for querying. Example :-
@ContentChild(StudentDirective) stu: StudentDirective;
- read : An optional property which from queried element reads a different token. Example :-
@ContentChild(StudentDirective, { read: ElementRef }) stu: StudentDirective
@ContentChildren has following metadata properties
- selector and read metadata properties are same with the only difference of returning a QueryList of elements.
- descendants: Initialized to a Boolean value. If true then direct children and other descendants are included in QueryList. If false then only direct children are included in QueryList. The default value is false.
Example :-
@ContentChildren(StudentDirective,{descendants: true}) stu: QueryList<StudentDirective>;
Example 1 :- @ContentChild and @ContentChildren using Directive
Create a directive named "highlight" using command ng generate directive highlight
import { Directive,ElementRef } from '@angular/core';
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
Create a child component "Student"
import {Component,AfterContentInit,ContentChild,ElementRef,QueryList,ContentChildren } from '@angular/core';
import {HighlightDirective} from '../directive/highlight.directive';
@Component({
selector: 'app-student',
template: `<ng-content></ng-content>`,
})
export class StudentComponent implements AfterContentInit {
@ContentChild(HighlightDirective) projectedcontent:HighlightDirective ; //ContentChild with only selector
@ContentChild(HighlightDirective,{read: ElementRef}) projectedcontent1:HighlightDirective ; //ContentChild with selector and read metadata property
@ContentChildren(HighlightDirective) projectedcontent2: QueryList<HighlightDirective>; //ContentChildren with selector
ngAfterContentInit() {
console.log(this.projectedcontent);
console.log(this.projectedcontent1);
let data: HighlightDirective[] = this.projectedcontent2.toArray();
console.log(data);
}
}
Create parent component "App"
import { Component} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent{
}
app.component.html
<app-student>
<p appHighlight>This is the <i>header</i> content from parent component.</p>
<p appHighlight>This is the <i>footer</i> content from parent component.</p>
</app-student>
Console Output:
Explanation: Above html defines two p tags which uses "highlight" directive. With @ContentChild with this directive will return only first element matching the selector, @ContentChild with directive and read metadata property return nativeElement and @ContentChildren with directive return all child elements matching selector and returns a QueryList which is converted to array.
Example 2: @ContentChild and @ContentChildren using Component
Create a child component "Student"
import {Component,Input } from '@angular/core';
@Component({
selector: 'app-student',
template: '<p>{{studentstream}}</p>'
})
export class StudentComponent {
@Input() studentstream;
}
Create another child component "Students"
import { Component,ContentChildren,QueryList,AfterContentInit,ContentChild } from '@angular/core';
import {StudentComponent } from '../student/student.component';
@Component({
selector: 'app-students',
template: '<ng-content></ng-content>'
})
export class StudentsComponent implements AfterContentInit {
@ContentChild(StudentComponent) stu: StudentComponent //ContentChild with component selector
@ContentChildren(StudentComponent) students: QueryList<StudentComponent> //ContentChildren with component selector
ngAfterContentInit() {
console.log(this.stu);
let data: StudentComponent[] = this.students.toArray();
console.log(data);
}
ngOnInit() {
}
}
Create parent component "App"
import { Component} from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent{
}
app.component.html
<app-students>
<app-student studentstream="Science"></app-student>
<app-student studentstream="Commerce"></app-student>
</app-students>
Console Output:
Explanation: In above example we are making two child components Student and Students using Student component within Students component in parent AppComponent. When the application runs it projects content of parent app component within <ng-content></ng-content> of child students component which further uses student component. Thus @ContentChild with StudentComponent returns single StudentComponent as it was within content DOM while @ContentChildren with StudentComponent returns all StudentComponent within content DOM.
Example 3: @ContentChild and @ContentChildren using ElementRef
StudentsComponent
import { Component,ContentChildren,QueryList,AfterContentInit,ContentChild,ElementRef } from '@angular/core';
import {StudentComponent } from '../student/student.component';
@Component({
selector: 'app-students',
template: '<ng-content></ng-content>'
})
export class StudentsComponent implements AfterContentInit {
@ContentChild("header") header: ElementRef;
@ContentChildren('header') headers: QueryList<ElementRef> ;
ngAfterContentInit() {
console.log(this.header);
let data: ElementRef[] = this.headers.toArray();
console.log(data);
}
ngOnInit() {
}
}
StudentComponent and AppComponent remains same
app.component.html
<app-students>
<app-student studentstream="Commerce"><div #header></div></app-student>
<app-student studentstream="Science"><div #header></div></app-student>
</app-students>
Console Output:
Explanation: Above example also uses content projection and provides element refrence within content DOM.
0 Comment(s)