При создании UI-библиотек один из главных вызовов — найти баланс между гибкостью и простотой API. Разберём, как правильно работать с проекцией контента в Angular.
Два основных подхода:
1️⃣ ng-content — для простых случаев
Отлично подходит, когда:
• Слоты всегда определены
• Не нужен условный рендеринг
• Контекст не требуется
<app-field>
<span slot="label">Label</span>
<input>
</app-field>
2️⃣ ng-template — для сложных сценариев
Используйте, когда нужно:
• Передать контекст в слот
• Ленивая инициализация контента
• Условный рендеринг
<ng-template #suffix let-control>
<button [class.bg-red]="control.invalid">
Search
</button>
</ng-template>
💡 Практический совет:
Создайте универсальную директиву для унификации работы со слотами:
@Directive({
selector: 'ng-template[slot]'
})
export class Slot {
readonly template = inject(TemplateRef);
readonly name = input.required<string>({ alias: 'slot' });
}Это даёт:
✅ Единообразный синтаксис
✅ Простую документацию
✅ Чистую идентификацию контента
🔸Реальный пример:
Компонент Accordion может комбинировать оба подхода:
🔸title — через ng-content (статичный текст)
🔸icon — через ng-template (нужен контекст открыт/закрыт)
🔸content — оба варианта (eager/lazy загрузка)
Итог ⬇️
Правильная работа со слотами — это не выбор между ng-content и ng-template, а понимание, когда использовать каждый инструмент. Комбинируйте оба подхода в зависимости от задачи, и ваши компоненты станут по-настоящему переиспользуемыми и удобными для других разработчиков.
📎 Статья
🎙 Новости
📝 База вопросов
