Angular contentchild and contentchildren

Introduction

ContentChild and ContentChildren are decorators in Angular which is used to retrieve the first matching element or list of elements(called QueryList) from the content DOM. They include elements which we defined in <ng-content></ng-content>. We can pass a directive, component, or template variable as the selector argument. Content queries are set just before the ngAfterContentInit hook so we need to implement this lifecycle hook to get access to the elements. If any change is there 

The main difference between ContentChild and ContentChildren is that ContentChild will return the first matching element whereas ContentChildren gives all the matching elements as QueryList. 

To query the directive, component or ElementRef using ContentChild or ContentChildren we can write as below:

  • Selector - Mention the name of the directive, component or local template references to query.
  • The query results are instantiated only before the ngAfterContentInit hook. So it is available only after this hook.

@ContentChildren(selector) name: Component/QueryList;

Now we will create one child component called child-example and we will go to child-example.component.html file and write the below code:

<h3 #heading>Can Be Accessed Using ViewChild</h3>
<ng-content></ng-content>

Now we have used directive to project content into the component dynamically. <ng-content> element is used as a placeholder to project content in the future. Now we will see the parent-example.html file where we have used the selector of the child-example component and projected content using <ng-content>. 

<div>
<app-child-example>
     <h3 heading="">Can Be Accessed Using ContentChild</h3> // Content Children Here for <app-child-example>
     <h2 heading="">Can Be Accessed Using ContentChild</h2> // Content Children Here for <app-child-example>

 </app-child-example>
</div>

Now we will go to child-example.component.ts file and see how content ContentChild is used to access content from the content DOM.

export class ChildExampleComponent implements OnInit, AfterContentInit {
  @Input() name: string;
  @ContentChild('heading') headingContent: any;
  @ContentChildren('heading') headingContent: any;
  constructor() { }

  ngOnInit(): void {
  }

  ngAfterContentInit() {
    console.log(this.headingContent);
  }
}

The elements which are present in between the opening and closing tags of the host element of a specific component are called Content children. We will get the first element matching in the content DOM using @ContentChild decorator. This code  @ContentChild('heading') headingContent: any; 

Angular contentchild and contentChildren look for the selector in the content DOM or called as light DOM. They will not select elements from the shadow DOM. Whereas the ViewCHild decorator looks for elements in the shadow DOM. 

Let us understand what is Shadow DOM and Light DOM. Suppose we have a component called example-component and let us understand about different DOM:

  • Shadow DOM - When we create components in Angular, the component template is kept under the shadowRoot of the shadow DOM. Shadow DOM is the tree hosted inside a component that is different from the main DOM tree. It is defined when we write a component. This concept is used to reuse components in Angular.
    @ViewChild and @ViewChildren decorator parameters will look for elements in the Shadow DOM.
  • Light DOM -  It is not the real template of your host element or component. It is defined by the elements which the user of the component supply using content projection or just insert in the shadow DOM using <ng-content>.
    @ContentChild and @ContentChildren decorator parameters will look for elements in the Light DOM(also called as Content DOM).

@Component({
  selector: 'example-component',
  template: `
     <h3 heading="">Can Be Accessed Using ViewChild</h3>
     <ng-content></ng-content>
  `;
})
class ExampleComponent { }

@Component({
  selector: 'another-example-component',
  template: `
 <div>
   <app-child-example>
      <h3 #heading>Can Be Accessed Using ContentChild</h3>
      <h2 #heading>Can Be Accessed Using ContentChild</h2>
   </app-child-example>
</div>
  `;
})
class anotherExampleComponent { }

Comments