Content Projection in Angular 10/9: Pass Data from a Parent Component to a Child Template with Ng-content

Content Projection in Angular 10/9: Pass Data from a Parent Component to a Child Template with Ng-content

Content projection is an concept that helps developers build reusable Angular components. It allows you to pass data from a parent component to a template of a child component. It's similar to transclusion in Angular.js

Content Projection with Angular 10 Example

Let's now see with a simple Angular 10 example how we can project content from a parent component to its child.

We'll be using Stackblitz for creating our content project example.

You can check our example from this link.

In Stackblitz, we already have a project generated with a couple of components - AppComponent and HelloComponent.

The hello component takes an input property called name and renders the following content:

<h1>Hello !</h1>

In ths src/app/app.component.html we include the hello component using it selector:

<hello  name=""></hello>

This is the full code of the hello component:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<h1>Hello !</h1>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() name: string;
}

As, you can see. Using the @Input decorator we can pass data to our component from the outside.

Read more about Angular TypeScript decorators.

Now, what if our data is more complex than just a name? Let's say we need to pass some HTML content to our component. This can be done with @Input but it's very effiecent and scalable and can be prone to errors.

Here comes content projection with <ng-content>.

Implementing Projected Content in Angular 10

Let's modify our hello component to accept projected content from the outside.

First, we need to use <ng-content> in our Angular component template. This is where the passed data will be projected:

import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<ng-content></ng-content>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
}

Now, in the src/app/app.component.html file, we pass the HTML content to our hello component as follows:

<hello>
    <h1>Hello Angular!</h1>
</hello>

We pass in the <h1>Hello Angular!</h1> code to the hello component to render it.

We can control what can be passed to the component using select in ng-content.

import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<ng-content select="h1"></ng-content>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
}

This means only <h1> tags will be passed and rendered. For example if you now pass the following content to the hello component, it will not be passed:

<hello>
    <h2>Hello Angular 10!</h2>
</hello>

You can also use the [attr] syntax in the select property to to accept only elements that have a specific attribute:

<ng-content select="[title]"></ng-content>

Now, to render the content, you need to make the following change:

<hello>
  <h1 title>Hello Angular 9!</h1>
</hello>

Conclusion

As a wrap-up, we've seen how to project content in Angular 10/9 using ng-content which helps you build reusable components.


  • Date: