🅰️ Angular Q112 / 128

Explain multi-slot content projection.

AI-Powered Answer ✓ Answered

Multi-slot content projection in Angular allows a component to accept and display multiple distinct pieces of content from its parent component at different designated locations within its own template. This enhances component reusability and flexibility by enabling more complex UI compositions.

What is Content Projection?

Content projection (formerly known as transclusion) is an Angular mechanism for inserting content from one component into another component. It allows you to create highly configurable and reusable components, where the inner content is provided by the consuming component rather than being hardcoded within the component itself.

Multi-Slot Content Projection

While basic content projection uses a single <ng-content> tag, multi-slot content projection extends this by using multiple <ng-content> tags, each with a 'select' attribute. The 'select' attribute specifies a CSS selector that determines which content from the parent component should be projected into that particular slot.

When Angular processes the content projected into a component, it matches the elements provided by the parent against the 'select' attributes of the <ng-content> tags. Content that matches a selector is placed into that slot. Content that doesn't match any 'select' attribute (or matches a selector on an <ng-content> without a 'select' attribute) is placed into the 'default' <ng-content> slot (the one without a 'select' attribute).

The 'select' Attribute

The 'select' attribute accepts a CSS selector, which can be any of the following:

  • Element name: e.g., select="p" will project all <p> elements.
  • CSS class: e.g., select=".title" will project elements with the class title.
  • Attribute: e.g., select="[header]" will project elements that have the header attribute.
  • ID: e.g., select="#myId" will project the element with ID myId (less common for projection).
  • Any combination of the above: e.g., select="div.footer[role=info]".

How it Works (Example)

Let's consider a reusable CardComponent that needs to display a title, some body text, and a footer, all provided by its parent. Multi-slot content projection is ideal for this scenario.

Component Definition (Card Component)

typescript
import { Component } from '@angular/core';

@Component({
  selector: 'app-card',
  templateUrl: './card.component.html',
  styleUrls: ['./card.component.css']
})
export class CardComponent { }
html
<!-- card.component.html -->
<div class="card">
  <div class="card-header">
    <ng-content select="[card-header]"></ng-content>
  </div>
  <div class="card-body">
    <ng-content select="[card-body]"></ng-content>
    <ng-content></ng-content> <!-- Default slot for any unselected content -->
  </div>
  <div class="card-footer">
    <ng-content select="[card-footer]"></ng-content>
  </div>
</div>

Parent Component Usage

html
<!-- app.component.html -->
<app-card>
  <h2 card-header>My Awesome Card Title</h2>
  <p card-body>This is the main content of the card. It's quite informative.</p>
  <button card-footer>Action Button</button>
  <small>This unselected content goes to the default slot.</small>
</app-card>

Key Takeaways

  • Enhanced Reusability: Components become more generic and adaptable to various contexts.
  • Separation of Concerns: The child component defines *where* content goes, while the parent defines *what* content is.
  • Flexibility: Allows for complex layouts where different parts of a component can be dynamically populated.
  • Readability: It's clear from the parent component's template what content is being passed to which slot.
  • Default Content: An <ng-content> without a 'select' attribute acts as a fallback for any projected content that doesn't match other selectors.