Условия: @if, @else и @switch

Новый синтаксис @if встроен прямо в шаблон: ни импортов, ни звёздочек — просто блоки, как в обычном языке программирования.

«Старый *ngIf был директивой-самозванцем под видом атрибута. Новый @if наконец честно выглядит как условие».

До Angular 17 условия писали через структурную директиву *ngIf. В современном Angular её заменил встроенный control flow — блоки @if, @for, @switch. Они не требуют импортов, работают быстрее и читаются естественнее. Условный рендеринг теперь выглядит так:

template: `
  @if (user) {
    <p>Привет, {{ user.name }}!</p>
  } @else if (loading) {
    <p>Загрузка...</p>
  } @else {
    <p>Войдите в аккаунт</p>
  }
`

Можно сохранить результат условия в переменную — удобно, когда выражение тяжёлое или это результат сигнала:

template: `
  @if (currentUser(); as user) {
    <h2>{{ user.name }}</h2>
    <p>Роль: {{ user.role }}</p>
  }
`

Для выбора из множества вариантов есть @switch — аналог конструкции switch в JavaScript:

template: `
  @switch (status) {
    @case ('active') { <span>Активен</span> }
    @case ('banned') { <span>Заблокирован</span> }
    @default { <span>Неизвестно</span> }
  }
`

Как работает под капотом

Раньше *ngIf разворачивался в <ng-template> и требовал импорта CommonModule — это создавало накладные расходы. Новые блоки компилятор переводит напрямую в эффективные инструкции, без оборачивающих шаблонов. Когда условие меняется, Angular добавляет или удаляет нужный участок DOM.

   @if (cond) { A } @else { B }
            |
   change detection вычисляет cond
            |
     cond === true  -> в DOM блок A, блок B удалён
     cond === false -> в DOM блок B, блок A удалён

Частые ошибки

  • Смешивать старое и новое. Не оборачивайте @if в *ngIf; выберите один стиль (предпочтительно новый).
  • Забыть фигурные скобки. В отличие от *ngIf, тело блока обязательно в { }.
  • Ожидать, что скрытый блок просто невидим. @if физически удаляет элементы из DOM, а не прячет их через CSS.

Best practices

  • Предпочитайте @if новым проектам — он не требует CommonModule и быстрее.
  • Используйте as-привязку, чтобы не вызывать сигнал многократно внутри блока.
  • Для трёх и более веток выбирайте @switch вместо лестницы @else if.

Итоги. Встроенный control flow заменил структурные директивы: @if/@else для условий, @switch для вариантов. Без импортов, быстрее, читаемее. Дальше — циклы через @for.

Закрепляем

Встроенный control flow — одно из самых заметных улучшений современного Angular. Раньше условный рендеринг писали через структурную директиву *ngIf, которая под капотом разворачивалась в служебный <ng-template> и требовала импорта CommonModule. Новые блоки @if, @else if, @else и @switch встроены прямо в язык шаблонов: ничего импортировать не нужно, компилятор переводит их в эффективный код, а читаются они как обычные условные конструкции из любого языка программирования.

Запомните важную деталь поведения: @if физически добавляет и удаляет элементы из DOM, а не прячет их через CSS вроде display:none. Это значит, что у скрытой ветки нет ни узлов в дереве, ни выполняемой логики — она буквально не существует, пока условие ложно. Отсюда и преимущество в производительности, и нюанс: состояние внутри скрытого блока (введённый текст, позиция прокрутки) теряется при удалении. Для простого переключения видимости с сохранением состояния иногда лучше подходит CSS, и понимать эту разницу полезно.

БлокАналог в JS
@if / @else if / @elseif / else if / else
@switch / @case / @defaultswitch / case / default
@if (x; as v)сохранить результат в переменную
Проверьте себя
1. Чем @if лучше устаревшего *ngIf?
AОн короче пишется и всё
BНе требует импорта CommonModule, быстрее и читается как обычное условие
CРаботает только с сигналами
DПрячет элемент через CSS вместо удаления
2. Что произойдёт с элементами внутри @if, когда условие станет ложным?
AОни станут невидимыми через display:none
BОни физически удаляются из DOM
CОни переместятся в конец страницы
DНичего, останутся как были