ContentChild and ContentChildren in Angular
Tags: angular, beginners, tutorial, webdev
Published: 2022-01-25 18:21:24

Today we will learn about `ContentChild` and `ContentChildren` in Angular.

On a high level `ContentChild` and `ContentChildren` are property decorators. They are used to query or helps to get a reference to the projected content. If you are not aware of Content Projection I would highly recommend you to go through [this post](https://dev.to/this-is-angular/content-projection-in-angular-1n9b).

Lets see our playground first. 
We have a `MyCardsComponent` component where few items are projected from the parent component (AppComponent).
`The parent Component Template Code`-
```
<app-my-cards>
    <div #header ngProjectAs='header'>Card Header</div>
    <span id='card-sub-header'>Card Sub Header</span>
    <div class="card-body">
        This is a card Body!!!
    </div>
    <footer title="card-footer">
        Card Footer.
    </footer>
</app-my-cards>
```
`The Child Component Code`-
```
<ng-content select='header'></ng-content>
<ng-content select='#card-sub-header'></ng-content>
<ng-content select='.card-body'></ng-content>
<ng-content select='[title]'></ng-content>
```
And the output till now -
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5soqkaea6ui9fhfwiy84.PNG)

Here we will try to get the reference of the projected content in the Child Component to do some manipulation (say adding some style). In this scenario [ViewChild](https://dev.to/this-is-angular/understanding-viewchild-and-viewchildren-in-angular-1aep) won't be helpful as it will not work. For this we need a new decorator called `ContentChild`/ `ContentChildren` decorator.

Lets paste in the below code in the `MyCardsComponent`-

```
  @ContentChild('header')
  cardHeaderData: ElementRef = {
    nativeElement: undefined
  };
```
So here in the above code we are defining a property `cardHeaderData` and decorating with `ContentChild`
cardHeaderData is of type `ElementRef` (A wrapper around the native element inside of a View)
Now the next question can come - okay we can access the element but where we can get hold of the element for the first time and how to prove that we got hold of the element? 
For this there is another lifecycle hook provided by Angular - the `ngContentInit()`.
This method is called once the projected content is initialized.

**Note**
Projected content will be accessible for the first time in the `ngAfterContentInit` lifecycle hook method.

So lets implement the function and see how it looks like. Paste in the below code -
```
  ngAfterContentInit() {
    this.cardHeaderData
    debugger;
  }
```
In the devtool when we inspect we can see the below -
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kj0g7u45sls218opsaoq.PNG)
Here 👆🏻 we can see that the reference of the element (which was projected) we can get using the `ContentChild` decorator and its a native element.
Once we get hold of the element we can do manipulation like adding a style programmatically and many more cool things. To change the style lets add the below code -
```
  ngAfterContentInit() {
    this.cardHeaderData.nativeElement.style.color = 'blue';
    this.cardHeaderData.nativeElement.style.backgroundColor = 
'yellow';
    this.cardHeaderData.nativeElement.style.fontSize = '24px';
  }
```
And you will see the below output -
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/63r58ti75h5grie7fnkm.PNG)
So using the property we can target the nativeElement and set the color and do all the DOM tricks.

Here we are targeting a HTML element (like div), but lets see what if we project a `Component` how to access that.

So lets create a component `ContentChildDemo`. You should be a ninja by now to create a component using CLI & even if you are 1 step away from becoming a ninja you can follow [this post](https://dev.to/anubhab5/creating-angular-component-129e).
And use the selector in `app.component.html` file like below -

```
<app-my-cards>
 <app-content-child-demo></app-content-child-demo>
</app-my-cards>
```
& in the `my-cards.component.ts` file lets add the below code -

```
<ng-content></ng-content>
```
You will see the below output. 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/spb71g7c6hidbmsppa7f.PNG)
So the content-projection is working 😊
Now lets create a property and decorate with ContentChild.
```
  @ContentChild(ContentChildDemoComponent)
  contentChildDemoProperty: ContentChildDemoComponent | undefined;
```
Here above you can see the ContentChildDecorator is accepting the name of the component you are trying to reference (In this case ContentChildDemoComponent), but in the first demo we were passing the reference (header) 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/29ciyh26gch8etbc6o96.PNG)
**Note**:
1️⃣ When accessing Component we just pass the name of the component.
2️⃣ When accessing a projected component, using the property you can even call a method present inside that projected content component.
3️⃣ When accessing a native element we need to add a **reference** and pass the same reference to the `ContentChild`

Now lets understand when the `ContentChildren` comes into play. 
Say in the above example we are projecting (passing from the parent) only 1 `ContentChildDemoComponent`. But what if a scenario arises where you are passing multiple components and you need to access them?

Something like below - 
```
<app-my-cards>
 <app-content-child-demo></app-content-child-demo>
 <app-content-child-demo></app-content-child-demo>
 <app-content-child-demo></app-content-child-demo>
</app-my-cards>
```
In the above case `ContentChild` will return only the first match (very important remember this point).
If you want to get hold of all the components projected you need to use the `ContentChildren` decorator.

Lets add a new property like below -
```
  @ContentChildren(ContentChildDemoComponent)
  contentChildrenDemoProperty: 
   QueryList<ContentChildDemoComponent> | undefined;
```
And in the `ngAfterContentInit` method -
```
  ngAfterContentInit() {
    this.contentChildrenDemoProperty
    debugger;
  }
```
And if we run the application and debug we will see the below -
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1wqxysad3wkxy2ji8e5f.PNG)
Here above we can see a `QueryList` (An unmodifiable list) is being returned. You can loop through and access every item. Same powerful heavy lifting you can do on all the matching items in the QueryList.

That's all for now.

Hope you enjoyed reading the post

If you liked it please _like_ ❤️ _share_ 💞 _comment_ 🧡.

Coming up `ChangeDetection`
So stay tuned.

I will be [tweeting](https://twitter.com/Anubhab_0905) more on `Angular` `JavaScript` `TypeScript` `CSS` tips and tricks.

So hope to see you there too 😃

**_Cheers_** 🍻 
_Happy Coding_