Skip to content

Angular ContentChild

AngularContentChild Cover

ContentChild is a property decorator in Angular that configures a content query or retrieves a reference to a projected content. We can use ContentChild in order to retrieve the first element (template reference, component, or directive) matching the selector from the DOM. We can define the component/directive for querying using the selector metadata property, and we can choose any class with @Component or @Directive decorator, a template reference (#component), a provider defined through a string token or a template using TemplateRef.

If this all seems a bit confusing, the best way to learn is using a practical example, so let us start with writing some code!

@ContentChild

We will use the same Card project playground we used last time. If you remember the code in our template, we projected two contents with selectors fav-day and dislikes. What if we would want to get the reference of projected content in order to do some direct changes to it? Well, we can use the above-mentioned @ContentChild decorator. First, let us create a new projected content using a template reference this time. This is our updated app.component.html file.

<app-user-card>
  <div class="more-data" fav-day>
    <h3>Favorite day:</h3>
    <p>Sunday</p>
  </div>
  <div class="more-data" dislikes>
    <h3>Dislikes:</h3>
    <p>The alarm clock</p>
  </div>
  <div class="more-data" expiry #expiry>
    <h3>Expiry Date:</h3>
    <p>20/05/2024</p>
  </div>
</app-user-card>

And this is our new user-card.component.html file:

<div class="wrapper">
  <div class="basic-info">
    <div class="image">
      <img
        src="https://avatars.dicebear.com/api/male/tom.svg?background=%230000ff"
      />
    </div>
    <div class="personal-data">
      <h3>Name:</h3>
      <p>Tom</p>
      <h3>Surname:</h3>
      <p>Doe</p>
    </div>
  </div>
  <ng-content select="[fav-day]"></ng-content>
  <div class="more-data">
    <h3>Likes:</h3>
    <p>Football, swimming, beer</p>
  </div>
  <ng-content select="[dislikes]"></ng-content>
  <ng-content select="[expiry]"></ng-content>
</div>

Let us notice two new things above. We used the template reference (#expiry) with the hash symbol in order to declare content that we will grab. Template references are used in order to be more detailed when working with projected data. This just means that we declared a new variable, expiry on our <div> element, which we will utilize later on. Everything else is more or less the same:

ContentChild – New Projected Content

In order to use this projected content, we need to change a couple of things in the logic of our component. This is our updated user-card.component.ts file:

import {
  AfterContentInit,
  Component,
  ContentChild,
  ElementRef,
  OnInit,
} from '@angular/core';

@Component({
  selector: 'app-user-card',
  templateUrl: './user-card.component.html',
  styleUrls: ['./user-card.component.css'],
})
export class UserCardComponent implements OnInit, AfterContentInit {
  @ContentChild('expiry') expiryReference: ElementRef;

  constructor() {}

  ngOnInit() {}

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

If we check our console we will see that the console.log(this.expiryReference); now returns the reference to our element which is amazing. But before we start manipulating our projected element let us explain these new concepts that we see here.

Let us start from the AfterContentInit lifecycle hook. It is called when the component’s external content has been attached, or when we project content, using <ng-content> tags. To put it simply we need to write our code regarding our projected content inside our method (you can test it by writing the console.log directive inside ngOnInit and seeing what you get back).

Then we have ElementRef which is a wrapper around a native DOM element. Using ElementRef we can access the underlying element and its DOM API without any issues.

ContentChild – nativeElement allows us direct access to the DOM

Now when we have the element we can dynamically add or remove styles, or do any other number of programmatic manipulations. For example, we can change the style of our element, by targeting the nativeElement and setting background colors, borders, padding, margin, font sizes and other properties:

import {
  AfterContentInit,
  Component,
  ContentChild,
  ElementRef,
  OnInit,
} from '@angular/core';

@Component({
  selector: 'app-user-card',
  templateUrl: './user-card.component.html',
  styleUrls: ['./user-card.component.css'],
})
export class UserCardComponent implements OnInit, AfterContentInit {
  @ContentChild('expiry') expiryReference: ElementRef;

  constructor() {}

  ngOnInit() {}

  ngAfterContentInit() {
    this.expiryReference.nativeElement.style.backgroundColor = 'salmon';
    this.expiryReference.nativeElement.style.padding = '10px';
    this.expiryReference.nativeElement.style.borderRadius = '10px';
  }
}

With the following result:

ContentChild – Changed Content

For the complete project, please look at the Stackblitz below:

Final Words

Well, this is a fairly simplistic overview of ContentChild. The truth is that the decorator is a lot more powerful because we can query whole directives or components inside our <ng-content></ng-content>. There is a caveat though, ContentChild only targets the first child component, in order to access/update multiple elements we would use ContentChildren which we will mention in the next post.

For more articles please click below, or check the blog.

3 thoughts on “Angular ContentChild”

  1. Pingback: Angular ContentChildren -

  2. Pingback: Angular ViewChild -

  3. Pingback: Angular ViewChildren -

Comments are closed.