Проекція вмісту (ng-content) в Angular
Що таке проекція контенту?
Проекція контенту дозволяє передавати HTML-контент з батьківського компонента в шаблон дочірнього компонента. Це еквівалент React'івського children або Vue'івських slots.
Проекція з одного слота
typescript
// card.component.ts
@Component({
selector: 'app-card',
standalone: true,
template: \`
<div class="card">
<div class="card-body">
<ng-content></ng-content>
</div>
</div>
\`
})
export class CardComponent {}html
<!-- Використання -->
<app-card>
<h2>Назва картки</h2>
<p>Будь-який контент може бути тут!</p>
<button>Дія</button>
</app-card>Проекція з кількох слотів
Використовуйте атрибут select, щоб проекціювати контент у конкретні слоти:
typescript
@Component({
selector: 'app-dialog',
template: \`
<div class="dialog">
<header>
<ng-content select="[dialog-header]"></ng-content>
</header>
<main>
<ng-content select="[dialog-body]"></ng-content>
</main>
<footer>
<ng-content select="[dialog-footer]"></ng-content>
</footer>
</div>
\`
})
export class DialogComponent {}html
<app-dialog>
<div dialog-header>
<h2>Підтвердити видалення</h2>
</div>
<div dialog-body>
<p>Ви впевнені, що хочете видалити цей елемент?</p>
</div>
<div dialog-footer>
<button (click)="cancel()">Скасувати</button>
<button (click)="confirm()">Видалити</button>
</div>
</app-dialog>Опції вибору
html
<!-- За атрибутом -->
<ng-content select="[header]"></ng-content>
<!-- За CSS класом -->
<ng-content select=".footer"></ng-content>
<!-- За елементом -->
<ng-content select="h2"></ng-content>
<!-- За компонентом -->
<ng-content select="app-icon"></ng-content>
<!-- За замовчуванням (незбіглий контент) -->
<ng-content></ng-content>Умовна проекція з ng-template
typescript
@Component({
selector: 'app-expandable',
template: \`
<div class="header" (click)="toggle()">
<ng-content select="[title]"></ng-content>
</div>
<div class="body" *ngIf="isOpen">
<ng-content select="[content]"></ng-content>
</div>
\`
})
export class ExpandableComponent {
isOpen = false;
toggle() { this.isOpen = !this.isOpen; }
}ContentChild та ContentChildren
Доступ до проекційованого контенту програмно:
typescript
@Component({ /* ... */ })
export class TabsComponent implements AfterContentInit {
@ContentChildren(TabComponent) tabs!: QueryList<TabComponent>;
ngAfterContentInit() {
// Доступ до проекційованих компонентів вкладок
const activeTabs = this.tabs.filter(tab => tab.active);
if (activeTabs.length === 0) {
this.tabs.first.active = true;
}
}
}html
<app-tabs>
<app-tab title="Головна">Контент головної</app-tab>
<app-tab title="Налаштування">Контент налаштувань</app-tab>
<app-tab title="Профіль" [active]="true">Контент профілю</app-tab>
</app-tabs>Важливо:
Проекція контенту з <ng-content> дозволяє створювати гнучкі, багаторазові обгорткові компоненти (картки, діалоги, макети). Використовуйте select для проекції з кількох слотів. Використовуйте @ContentChildren для програмного доступу до проекційованих компонентів. Це версія Angular для пропозиції дітей React або слотів Vue.
Коротка відповідь
Для співбесідиPremium
Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.