How to access ng-content with @ContentChild – Angular Component ?
This tutorial guides you on how to access ng-content using @ContentChild decorator within Angular component in Angular application.
Access ng-content using @ContentChild – Angular Component
You had learnt in our previous tutorials on how to project contents into angular components using ng-content, were we could project content from parent component (App Component) in to the designated child component.
Also, learnt View Child and how to access in life cycle hooks in another tutorial. In this tutorial you will learn how to decorate a parameter that will be used to configure content query i.e., it can be used to get the first element or the directive matching the selector from the content DOM.
Note, content queries are set before the ngAfterContentInit() callback is called.
For example, refer comment “Projecting content into component with ng-content“. I had placed the local reference “#contentParagraph” on the pragraph.
app.component.html
<div class="container"> <app-create-item (itemAdded)="onItemAdded($event)" (itemSpecAdded)="onItemSpecAdded($event)"></app-create-item> <hr> <div class="row"> <div class="col-xs-12"> <button class="btn btn-primary" (click)="onChangeComponentElement()">Change item element</button> <!-- To Demo ngOnDestroy() --> <button class="btn btn-danger" (click)="onDestroyComponentElement()"> Destroy component</button> <app-item-element *ngFor="let elem of itemElems" [itemElem] = "elem" [title] = "elem.title"> <!-- Projecting content into component with ng-content --> <p #contentParagraph> <strong *ngIf="elem.type === 'item'" style="color: orange">{{ elem.desc }}</strong> <em *ngIf="elem.type === 'spec'">{{ elem.spec }}</em> </p> </app-item-element> </div> </div> </div>
Once you project content into App Component using ng-content. Now, using the template reference variable “#contentParagraph” you can access ng-content using @ContentChild within Angular component (ItemElementComponent) class as shown below.
item-element.component.ts
import { AfterViewChecked, AfterViewInit, AfterContentChecked, AfterContentInit, Component, DoCheck, Input, OnChanges, OnInit, SimpleChanges, OnDestroy, ViewChild, ElementRef, ContentChild } from '@angular/core'; @Component({ selector: 'app-item-element', templateUrl: './item-element.component.html', styleUrls: ['./item-element.component.css'], }) export class ItemElementComponent implements OnInit, OnChanges, DoCheck, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, OnDestroy{ @Input() itemElem : {type: string, title: string, desc: string, spec: string}; @Input() title : string; @ViewChild('heading', {static: true}) header : ElementRef; @ContentChild('contentParagraph', {static: true}) paragraph : ElementRef; constructor() { console.log("constructor called....."); } ngOnChanges(changes: SimpleChanges) { console.log("ngOnChanges called....."); console.log(changes); } ngOnInit(): void { console.log("ngOnInit called....."); console.log('Header Content:' + this.header.nativeElement.textContent); console.log('Paragraph text Content:' + this.paragraph.nativeElement.textContent); } ngDoCheck(){ console.log("ngDoCheck called....."); } ngAfterContentInit(){ console.log("ngAfterContentInit called....."); console.log('Paragraph text Content:' + this.paragraph.nativeElement.textContent); } ngAfterContentChecked(){ console.log("ngAfterContentChecked called....."); } ngAfterViewInit(){ console.log("ngAfterViewInit called....."); console.log('Header Content::::::' + this.header.nativeElement.textContent); } ngAfterViewChecked(){ console.log("ngAfterViewChecked called....."); } ngOnDestroy(){ console.log("ngOnDestroy called....."); } }
Note, you need to add {static: true} as a second argument, if you are planning to access the selected element inside of ngOnInit(). And if you don’t access the selected element in ngOnInit(), but elsewhere in your component the set {static: false} instead.
Also, note if you are using Angular 9+, you need to add {static:true} if needed, but not {static:false}
Of course, you can’t access the value “paragraph” of before you reach ngAfterContentInit() as shown below***.
item-element.component.ts:43 constructor called..... item-element.component.ts:47 ngOnChanges called..... item-element.component.ts:48 {itemElem: SimpleChange, title: SimpleChange} item-element.component.ts:52 ngOnInit called..... ***item-element.component.ts:53 Header Content: ***item-element.component.ts:54 Paragraph text Content: item-element.component.ts:58 ngDoCheck called..... item-element.component.ts:62 ngAfterContentInit called..... ***item-element.component.ts:63 Paragraph text Content:Android phone by Google
That’s it. You had learnt how to project contents into angular components using ng-content. Also, learnt how to access ng-content using @ContentChild decorator within Angular component.
Hope it helped 🙂
- Call ngOnInit() again from another function – Angular 9 ?
- ngOnChanges get new value and previous value – Angular
- Why do we need ngDoCheck lifecycle hook – Angular ?
- Global Angular CLI version is greater than your local version
- Upgrade Angular CLI to the latest version Angular 9 or 10 ?
- How to use new static option in ViewChild Angular 9 ?
- Project contents into angular components using ng-content
- Call ngOnInit() again from another function – Angular 9 ?
- ngAfterContentInit with Example – Angular
- How Angular Encapsulates Styles using ViewEncapsulation ?
- ngAfterViewInit with Example – Angular
- ngAfterContentChecked with Example
- ngOnDestroy Example Angular
- Angular Component : In which lifecycle hook you can check value of DOM element ?
- @ContentChild TypeError: Cannot read property ‘nativeElement’ of undefined
- How to select an element in a component template – Angular ?