Accessing Child Component Instances using ContentChild and ContentChildren

Gurinderpal Singh Narang
3 min readDec 4, 2023

--

In Angular, @ContentChild and @ContentChildren decorators are used to access child components or directives that are projected into the component using the <ng-content> element. These decorators work with the content of the component, which is the content projected by the parent component.

Here’s a brief explanation of how to use @ContentChild and @ContentChildren:

@ContentChild:

  • Similarly like @ViewChild , @ContentChild is used to get the first instance of a child component or directive that matches the specified selector within the projected content.
  • Typically used when there is a single occurrence of the child component or directive.
  • Should be used in conjunction with the ngAfterContentInit lifecycle hook.

@ContentChildren:

  • Used to get a QueryList containing all instances of child components or directives that match the specified selector within the projected content.
  • Suitable when there are multiple occurrences of the child component or directive.
  • Should be used in conjunction with the ngAfterContentInit lifecycle hook.

ngAfterContentInit:

  • A lifecycle hook called after the component’s content has been projected and initialized.
  • Provides a safe place to interact with child components or directives within the content.
  • Use it when you need to access content children using @ContentChild or @ContentChildren.

Here is simple code example:

Parent Component:

<div class="courses" *ngIf="course">
<course-card (courseSelected)="onCourseSelected($event)" [course]="course">
<img select="[img]"
src="{{ course.iconUrl }}"
#courseImage
/>
<div class="course-description" select="[description]">
{{ course?.longDescription }}
</div>
<h5>Remaining content</h5>
</course-card>
</div>

Here, in the parent component, #courseImage is projected in child using <ng-content> .

Child Component:

<div class="course-card" [ngClass]="cardClasses()" *ngIf="showCard">
<div class="course-title" *ngIf="course?.description">
{{ course?.description }}
</div>
<ng-content select="img"></ng-content>
<ng-content select=".course-description"></ng-content>
<ng-content></ng-content>

<button (click)="onCourseViewed(course)">View course</button>
</div>

Now, in the child component’s .ts file, if you try to get the reference of #courseImage using @ViewChild , it will return undefined.

  @ViewChild('courseImage')
courseImage;

ngAfterViewInit() {
console.log("Course Image: ", this.courseImage);
}
console for the above code

Now, if you try to get this using @ContentChild, you will get the desired element. Here is the changes which you need to made in the code.

 @ContentChild('courseImage')
courseImage;

ngAfterContentInit() {
console.log("Course Image: ", this.courseImage);
}

Note: You need to use ngAfterContentInit lifecycle hook instead of ngAfterViewInit . The ngAfterContentInit lifecycle hook is guaranteed to be called after the content has been projected and initialized.

Summary, Keep in mind that if you’re trying to access the content projected through ng-content in a parent component, you won't be able to do so directly using @ViewChild in the child component. Instead, you might need to pass data or references through inputs and outputs to achieve the desired communication between components or you need to use @ContentChild and @ContentChildren .

--

--

No responses yet