Проекция контента
В этом посте я отвечу на 3 основных вопроса (Что, Почему и Как).
Что такое проекция содержания?
В Angular проекция содержимого используется для проецирования содержимого в компоненте (angular.io).
Почему мы его используем?
- Многие компоненты в вашем приложении используют одинаковую структуру и стиль, но их содержимое отличается, другими словами, возможность повторного использования.
- Вы создаете компонент только для отображения, а другой компонент - для обработки действий пользователя, другими словами Разделение проблем.
Как мы это используем?
С одним слотом
В основном вы просто добавляете <ng-content></ng-content>
в свой html, и он будет заменен содержимым извне компонента.
<!-- inside container component --> <ng-content></ng-content>
<!-- inside another component --> <container-component> <p>Content Here</p> </container-component>
Многослотовая (целевая проекция)
ng-content
принимает атрибутselect
, который позволяет нам установить конкретное имя селектора CSS для этого слота.
- Использование элемента (ов)
name
<!-- inside container component --> <ng-content select="slot-one"></ng-content>
<!-- inside another component using container component --> <container-component> <slot-one>Content For Slot one</slot-one> </container-component>
Если вы используете его в обычной настройке angular cli, вы столкнетесь с ошибкой, если сейчас используете тег <slot-one>
.
Отклонение необработанного обещания: ошибки синтаксического анализа шаблона: элемент "slot-one" неизвестен, Angular не распознает тег
slot-one
.slot-one
не является ни директивой, ни компонентом.
Быстрый способ обойти эту ошибку - добавить свойство метаданных схемы в ваш модуль, установить значение NO_ERRORS_SCHEMA в вашем файле модуля.
// app.module.ts
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core'; // import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component'; import { ContainerComponent } from './container-component';
@NgModule({ imports: [BrowserModule], declarations: [AppComponent, ContainerComponent], bootstrap: [AppComponent], schemas: [NO_ERRORS_SCHEMA] // add this line }) export class AppModule {}
- Использование атрибутов
[name]
|[name][another-name]
<!-- inside container component --> <!-- Using Single Attribute --> <ng-content select="[slot-one]"></ng-content> <!-- Using Multiple Attributes --> <ng-content select="[slot][two]"></ng-content>
<!-- inside another component using container component --> <container-component> <p slot-one>Content For Slot one</p> <p slot two>Content For Slot two</p> </container-component>
- Использование атрибута со значением
[name="vlue"]
<!-- inside container component --> <ng-content select="[slot='one']"></ng-content> <ng-content select="[slot='two']"></ng-content>
<!-- inside another component using container component --> <container-component> <p slot="one">Content For Slot one</p> <p slot="two">Content For Slot two</p> </container-component>
- Использование класса (ов)
.name
|.name.another-name
<!-- inside container component --> <!-- Using Single Class --> <ng-content select=".slot-one"></ng-content> <!-- Using Multi Class --> <ng-content select=".slot.two"></ng-content>
<!-- inside another component using container component --> <container-component> <p class="slot-one">Content For Slot one</p> </container-component>
- Без использования обертывания div
как вы можете видеть в предыдущем примере, вы можете использовать целевой слот, обернув свой контент с помощью div или element и прикрепив к нему селектор, но в некоторых кассах вы просто хотите поместить его туда.
Использование атрибута
ngProjectAs
angular в теге ng-container или желаемом теге and.
<!-- inside container component --> <!-- Element --> <ng-content select="slot-one"></ng-content> <!-- Attributes --> <ng-content select="[slot-one]"></ng-content> <ng-content select="[slot][two]"></ng-content> <!-- Attributes with Value --> <ng-content select="[slot='one']"></ng-content> <ng-content select="[slot='two']"></ng-content>
<!-- Inside ngProjectAs use projected name--> <ng-container ngProjectAs="slot-one"> Very <strong>important</strong> text with tags. </ng-container> <ng-container ngProjectAs="[slot][two]"> Very <strong>important</strong> text with tags. </ng-container>
Внутри *ngFor
// Container Component @Component({ ... template: ` <li *ngFor="let item of items"> <ng-template [ngTemplateOutlet]="templateRef" [ngTemplateOutletContext]="{$implicit: item}"></ng-template> </li> ` }) class TabsComponent { @ContentChild(TemplateRef) templateRef:TemplateRef; @Input() items; }
<!-- data here is the array input for container-component --> <container-component [items]="data"> <ng-template let-item> <!-- here we can use item --> {{ item }} </ng-template> </container-component>