Проекция содержимого через ng-content¶
30.09.2026
Этот материал предполагает, что вы уже прочитали руководство по основам. Если Angular для вас в новинку, начните с него.
Часто нужен компонент-контейнер под разное содержимое. Например, своя карточка:
1 2 3 4 5 6 7 | |
Элемент <ng-content> ставят туда, куда должно попасть содержимое:
1 2 3 4 5 6 7 | |
<ng-content> похож на нативный элемент <slot>, но добавляет возможности, специфичные для Angular.
Если у компонента есть <ng-content>, дочерние узлы элемента-хоста отрисовываются, то есть проецируются, на место этого <ng-content>:
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 | |
1 2 3 4 5 6 | |
Дочерние узлы, переданные таким образом, Angular называет содержимым компонента. Это не то же самое, что представление: представление — элементы, заданные в шаблоне компонента.
Элемент <ng-content> — не компонент и не DOM-элемент. Это особый заполнитель: он говорит Angular, куда отрисовать содержимое. Компилятор обрабатывает все элементы <ng-content> на этапе сборки. Во время выполнения <ng-content> нельзя вставить, удалить или изменить. К <ng-content> нельзя добавить директивы, стили или произвольные атрибуты.
Не включайте <ng-content> условно через @if, @for или @switch. Angular всегда создаёт экземпляр и DOM-узлы для содержимого, которое попадает в заполнитель <ng-content>, даже если этот заполнитель скрыт. Условная отрисовка содержимого компонента описана в Фрагменты шаблона.
Несколько мест для содержимого¶
Angular умеет раскладывать разные элементы по разным заполнителям <ng-content> по CSS-селектору. Продолжая пример с карточкой, заголовок и тело можно развести атрибутом select:
1 2 3 4 5 6 7 8 9 10 11 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 9 10 11 12 | |
1 2 3 4 5 6 7 8 | |
Заполнитель <ng-content> принимает те же CSS-селекторы, что и селекторы компонентов.
Если есть один или несколько заполнителей <ng-content> с атрибутом select и один <ng-content> без select, последний забирает все элементы, которые не совпали ни с одним select:
1 2 3 4 5 6 7 | |
1 2 3 4 5 6 | |
1 2 3 4 5 6 7 8 9 | |
Если у компонента нет заполнителя <ng-content> без атрибута select, элементы, которые не совпали ни с одним заполнителем, в DOM не попадают.
Запасное содержимое¶
Если у заполнителя <ng-content> нет подходящего дочернего содержимого, Angular может показать запасное содержимое. Его задают дочерними узлами самого элемента <ng-content>.
1 2 3 4 5 6 | |
1 2 3 4 5 | |
1 2 3 4 5 6 7 8 | |
Псевдоним содержимого для проекции¶
Специальный атрибут ngProjectAs задаёт элементу CSS-селектор. Когда элемент с ngProjectAs сверяют с заполнителем <ng-content>, Angular сравнивает значение ngProjectAs, а не сам элемент:
1 2 3 4 5 6 | |
1 2 3 4 5 6 | |
1 2 3 4 5 6 7 8 | |
ngProjectAs принимает только статические значения и не привязывается к динамическим выражениям.
Ограничения¶
Проецируемое содержимое живёт в представлении родителя¶
Проецируемое содержимое отрисовывается внутри принимающего компонента, но принадлежит тому компоненту, который его объявил. Angular ведёт его как часть представления родителя, и из этого следуют два побочных эффекта.
Обнаружение изменений. Проецируемое содержимое проверяется, когда обнаружение изменений запускает родитель. Если принимающий компонент использует OnPush, Angular может пропустить проверку его собственного шаблона, но не пропустит проецируемое содержимое: оно принадлежит родителю.
1 2 3 4 5 | |
Инъекция зависимостей. Проецируемое содержимое получает зависимости из инжектора родителя, а не из viewProviders принимающего компонента. Подробнее в Провайдеры и viewProviders.
Не все библиотечные компоненты принимают проецируемых потомков¶
Некоторые компоненты — меню, вкладки, списки — ищут потомков через ContentChildren и сами настраивают поведение: навигацию с клавиатуры, фокус, атрибуты ARIA. Они написаны в расчёте на то, что потомки принадлежат им напрямую, поэтому проекция чужого содержимого внутрь ломает это поведение неочевидным образом.
Например, если обернуть элементы <mat-menu-item> лишним слоем и спроецировать их в <mat-menu>, навигация с клавиатуры и поддержка экранных дикторов могут молча сломаться. Запрос по-прежнему находит пункты, но внутренняя настройка, которая делает их интерактивными, может работать неправильно, когда пункты приходят из другого контекста представления.
Если библиотечный компонент сам управляет поведением потомков, сначала загляните в его документацию: проекция содержимого может быть не предусмотрена.
Источник: https://angular.dev/guide/components/content-projection