Блог Михаила Крамера. PHP и JS
Слоты в компонентах Angular

Предположим вам нужно разработать компонент какой-нибудь панели, которая повторяется много раз в дизайне. У неё есть заголовок, у неё есть футер, у неё есть контент. Как сделать это оптимальным образом

Первое что приходит на ум - это @Input(), но в свойства мы передаём простые строки. А если местами нам необходимо передавать какую-то вёрстку? Второй вариант - это использование ng-template. Но в данном случае ng-template будет выглядеть не очень красиво, поскольку заголовок и футтер как бы получатся вне панели. К счастью, у ангуляра есть ещё один способ передать контент внутрь компонента - это слоты. И сделаны они достаточно удобно. Нам поможет свойство select компонента <ng-content>. В него вы передаёте любой css-дескриптор, по которому из контента компонента можно выбрать тот или иной элемент. Вот пример кода такой панели:

panel.component.ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-panel',
  templateUrl: './panel.component.html',
  styleUrls: ['./panel.component.scss']
})
export class PanelComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }

}
panel.component.scss
:host {
  border: 1px solid black;
  display: block;
}

.header {
  background: lightblue;
}
.footer {
  background: lightgreen;
}
panel.component.html
<div class="header">
  <ng-content select="[header]"></ng-content>
</div>
<div class="content">
  <ng-content select="[panelContent]"></ng-content>
</div>
<div class="footer">
  <ng-content select="[footer]"></ng-content>
</div>

И как её использовать в другом компоненте:

<app-panel>
  <ng-container header>Заголовок</ng-container>
  <ng-container panelContent>Контент</ng-container>
  <ng-container footer>Футер</ng-container>
</app-panel>

В заключении хочу отметить, что если не указать свойства select у <ng-content>, то будет подставлен весь контент, заключённый в теги компонента

Комментарии