When building a Design System or a library of shared components, the most difficult challenge is balancing consistency with flexibility.
You want all your Modals to look the same (consistency), but some Modals contain forms, others contain text, and others contain complex grids (flexibility).
The Architectural Pattern that solves this is Content Projection (specifically Multi-Slot Projection).
The Basics: The "Select" API
When you build a container, you define its API not by Inputs, but by Slots.
@Component({
selector: 'app-layout',
template: `
<header>
<ng-content select="nav"></ng-content>
</header>
<main>
<ng-content></ng-content>
</main>
`
})
export class AppLayoutComponent {}
The Senior "Gotcha": Wrapper Elements
Here is a problem 99% of devs hit.
Imagine your app-layout expects a <nav> tag because of select="nav".
But you want to project a custom component called <app-top-bar>.
<app-layout>
<app-top-bar></app-top-bar>
</app-layout>
Your app-top-bar will fall into the default slot (Main), not the Header slot.
The Junior Fix:
Wrap it in a nav tag.
<app-layout>
<nav> <app-top-bar></app-top-bar>
</nav>
</app-layout>
Problem: You just introduced an extra DOM node (<nav>) that might mess up your Flexbox or Grid layout.
The Senior Fix: ngProjectAs
Angular has a special attribute that allows you to "disguise" an element so it matches a specific selector, without adding extra DOM nodes.
<app-layout>
<app-top-bar ngProjectAs="nav"></app-top-bar>
</app-layout>
This tells Angular: "Treat this component as if it were a <nav> tag for the purposes of projection."
The "Projected Content" Lifecycle Risk
As a Senior Developer, you need to know the performance cost.
Projected content is instantiated EAGERLY.
If you project a heavy component:
<app-modal><app-heavy-chart></app-heavy-chart></app-modal>
The app-heavy-chart is created, its constructor runs, and its ngOnInit runs immediately, even if the modal is hidden via display: none.
The Optimization:
If the content is extremely heavy, do not use basic Content Projection. Use Template Projection (ng-template).
<app-modal [contentTemplate]="myChart"></app-modal>
<ng-template #myChart>
<app-heavy-chart></app-heavy-chart>
</ng-template>
// Child (Modal)
@Input() contentTemplate: TemplateRef<any>;
<ng-container *ngTemplateOutlet="contentTemplate"></ng-container>
This ensures the chart is not instantiated until the Modal actually renders the template outlet.
Mastering these nuances—ngProjectAs and TemplateRef—is what separates a component library author from a component user.