Angular: динамические компоненты и проекция контента
ViewEncapsulation
Определяет, будут ли стили компонента влиять на всё приложение:
- Emulated (по умолчанию) — стили компонента изолированы через эмуляцию (атрибуты); внешние стили могут проникать.
- ShadowDom — настоящая изоляция через Shadow DOM; внешние стили не проникают. (Старое значение
Nativeудалено в Angular 11.) - None — стили компонента видны всем компонентам приложения.
Content Projection и ng-content
Паттерн, при котором контент вставляется (проецируется) внутрь другого компонента через <ng-content> — плейсхолдер (слот) для контента родителя.
<ng-content select="..."> — именованный слот: выборочно проецирует контент в конкретные слоты.
<!-- родитель -->
<app-child>
<div slot="header">Header</div>
<div slot="content">Content</div>
</app-child>
<!-- child -->
<ng-content select="[slot=header]"></ng-content>
<ng-content select="[slot=content]"></ng-content>@ContentChild— ссылка на один спроецированный элемент/компонент/директиву/шаблон.@ContentChildren— коллекция спроецированных элементов, подходящих под селектор.
ViewContainerRef и TemplateRef
- ViewContainerRef — контейнер, куда можно динамически вставлять и удалять view (компоненты, шаблоны). Обычно получают через
@ViewChild(..., { read: ViewContainerRef }). - TemplateRef — представляет встроенный шаблон (
<ng-template>). Вместе сViewContainerRef.createEmbeddedView()создаёт и вставляет динамические view.
@ViewChild("container", { read: ViewContainerRef }) container!: ViewContainerRef;
@ViewChild("tpl", { read: TemplateRef }) tpl!: TemplateRef<any>;
embed() {
this.container.createEmbeddedView(this.tpl);
}Проброс контекста в шаблон через ngTemplateOutlet:
<div *ngFor="let item of items"
[ngTemplateOutlet]="itemTpl"
[ngTemplateOutletContext]="{ $implicit: item }"></div>
<ng-template #itemTpl let-item>{{ item }}</ng-template>ngComponentOutlet
Директива для динамического рендеринга компонента по его типу — создаёт и вставляет компонент в DOM на основе условий времени выполнения.
<ng-container *ngComponentOutlet="dynamicComponent"></ng-container>