Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Проекция содержимого: ng-content

Входы передают в компонент данные, но иногда нужно передать целый кусок разметки: заголовок с иконкой, форму, список. Для этого служит проекция содержимого — тег <ng-content> отмечает место, куда Angular вставит всё, что написано между открывающим и закрывающим тегом компонента.

Компонент-обёртка

Сделаем карточку с рамкой и тенью, в которую можно положить что угодно:

ng generate component card
<!-- src/app/card/card.html -->
<div class="card">
  <ng-content />
</div>
/* src/app/card/card.css */
.card {
  padding: 16px;
  border-radius: 8px;
  box-shadow: 0 2px 6px rgb(0 0 0 / 0.15);
}

Класс Card в src/app/card/card.ts остаётся пустым — вся работа в шаблоне.

Использование

Родитель импортирует Card и пишет содержимое внутри тега:

<!-- src/app/app.html -->
<app-card>
  <h2>Список дел</h2>
  <app-todo-list />
</app-card>
// src/app/app.ts
import { Component } from '@angular/core';
import { Card } from './card/card';
import { TodoList } from './todo-list/todo-list';
 
@Component({
  selector: 'app-root',
  imports: [Card, TodoList],
  templateUrl: './app.html',
  styleUrl: './app.css',
})
export class App {}

Заголовок и список дел окажутся внутри блока с тенью — на месте <ng-content />. Без этого тега содержимое просто не появится на странице.

Несколько слотов

Атрибут select задаёт, какие элементы попадут в данный слот. Значение — CSS-селектор:

<!-- src/app/card/card.html -->
<div class="card">
  <header class="card-header">
    <ng-content select="[card-title]" />
  </header>
  <ng-content />
</div>
<!-- src/app/app.html -->
<app-card>
  <h2 card-title>Список дел</h2>
  <app-todo-list />
</app-card>

Элемент с атрибутом card-title попадёт в шапку карточки, а всё остальное — в слот без select. Атрибут card-title ничего не делает сам — это просто метка для селектора.

Чем отличается от input()

СпособЧто передаётПример
input()Данные: строки, числа, объектыЗадача для app-todo-item
ng-contentГотовую разметку и компонентыСодержимое карточки

Компонент с ng-content не знает, что ему положат внутрь, — поэтому он подходит для обёрток: карточек, модальных окон, вкладок.

Частая ошибка

Ждать, что @if вокруг <ng-content /> в дочернем компоненте не даст создать содержимое. Компоненты внутри тега <app-card> создаёт родитель, и они создаются всегда, даже если слот скрыт. Если тяжёлый компонент нужен не всегда, оборачивайте в @if его самого — в шаблоне родителя.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.