Ng-Content & Content Projection in Angular


Cards are a fundamental user interface element used to structure and display content. In Angular, we can create versatile and customizable card components using the ng-content directive. ng-content enables us to project content from the parent component into the child component, making it highly adaptable for various use cases. One of the powerful features of ng-content is the select attribute, which allows us to selectively project specific content into the child component.

In this tutorial, we’ll guide you through the process of creating a customizable card component using ng-content, with a focus on how to use the select attribute to precisely control which content gets projected into the child component.

Prerequisites

Before we dive in, ensure you have the following prerequisites in place:

  1. Basic knowledge of Angular.
  2. Angular CLI installed on your system.
  3. A code editor of your choice (e.g., Visual Studio Code).

Getting Started

Let’s begin by creating a new Angular project and generating the card component.

ng new customizable-card-demo
cd customizable-card-demo
ng generate component card

This will set up a new Angular project and generate a card component for us.

Building the Customizable Card Component

  1. Open the card.component.html file and define the basic structure of the card. We’ll keep it simple with a card title, content, and buttons.
<div class="card">
  <div class="card-title">
    <ng-content select="[card-title]"></ng-content>
  </div>
  <div class="card-content">
    <ng-content></ng-content>
  </div>
  <div class="card-actions">
    <ng-content select="[card-actions]"></ng-content>
  </div>
</div>

In the code above, notice the use of the select attribute within ng-content. We’re using [card-title], :host, and [card-actions] as selectors to target specific elements or attributes for content projection. This means that content enclosed in elements with these attributes or elements themselves will be projected into the respective <ng-content> tags within the card component.

  1. Style your card by adding CSS rules to the card.component.css file. You can customize the styles according to your project’s design.
.card {
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 16px;
  margin: 16px;
  background-color: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.card-title {
  font-size: 18px;
  font-weight: bold;
  margin-bottom: 12px;
}

.card-content {
  font-size: 16px;
}

.card-actions {
  margin-top: 16px;
  display: flex;
  justify-content: space-between;
}
  1. In the app.component.html file, create a sample card with a custom title, content, and buttons:
<app-card>
  <div card-title>Custom Card Title</div>
  <p>This is the content of the custom card component. You can place any content here.</p>
  <div card-actions>
    <button (click)="onButton1Click()">Button 1</button>
    <button (click)="onButton2Click()">Button 2</button>
  </div>
</app-card>
  1. In the app.component.ts file, add the corresponding event handlers:
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <app-card>
      <div card-title>Custom Card Title</div>
      <p>This is the content of the custom card component. You can place any content here.</p>
      <div card-actions>
        <button (click)="onButton1Click()">Button 1</button>
        <button (click)="onButton2Click()">Button 2</button>
      </div>
    </app-card>
  `
})
export class AppComponent {
  onButton1Click() {
    alert('Button 1 Clicked');
  }

  onButton2Click() {
    alert('Button 2 Clicked');
  }
}
  1. Serve your Angular application and open it in a web browser:

ng serve --open

You should now see your customizable card displayed in the browser with the specified title, content, and buttons. Clicking the buttons will trigger the corresponding events.

Understanding the select Attribute

The select attribute in ng-content is a powerful tool for precise content projection. It allows you to target specific elements or attributes within the parent component’s template. When you use the select attribute, Angular looks for elements in the parent component that match the provided selector and projects only those elements into the corresponding <ng-content> tag in the child component.

In our example, we used [card-title], :host, and [card-actions] as selectors. Here’s what each of them does:

  • [card-title]: This selector looks for elements with the card-title attribute in the parent component’s template. Any content enclosed within such elements is projected into the <ng-content select="[card-title]"> tag in the child component. This allows you to customize the card’s title.

  • :host: This special selector refers to the host element itself, which is the <app-card> element in our case. Using :host, we can project content that is not enclosed within any specific element in the parent component’s template. This is useful for projecting general content into the card.

  • [card-actions]: Similar to [card-title], this selector targets elements with the card-actions attribute in the parent component’s template. Content within these elements is projected into the <ng-content select="[card-actions]"> tag in the child component, allowing you to customize card actions.

By using the select attribute, you gain fine-grained control over which parts of the parent component’s content should be included in the child component, making your card component highly customizable and versatile.

Conclusion

In this tutorial, we’ve explored how to create a customizable card component in Angular using ng-content. We’ve also delved into the power of the select attribute, which enables us to selectively project specific content into the child component based on elements or attributes. This approach provides a flexible and reusable solution for creating cards with tailored content and functionality. You can further enhance your card component by adding more features, such as images or additional styling options.

Demo

Next Post Previous Post
No Comment
Add Comment
comment url