Encodera

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

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

Оглавление

Атрибутные директивы

Директива добавляет поведение к обычному элементу. Компонент — это директива с шаблоном, а атрибутная директива шаблона не имеет: её пишут как атрибут у любого тега, и она меняет вид или поведение этого тега. Например, подсветка строки при наведении мыши.

Создание директивы

ng generate directive highlight

CLI создаст файл src/app/highlight.ts с классом Highlight (в версиях до 20 — highlight.directive.ts и HighlightDirective):

// src/app/highlight.ts
import { Directive } from '@angular/core';
 
@Directive({
  selector: '[appHighlight]',
  host: {
    '[style.backgroundColor]': "'lightyellow'",
  },
})
export class Highlight {}

Селектор в квадратных скобках означает «элемент с атрибутом appHighlight». Свойство host задаёт привязки к самому этому элементу — здесь фон.

Применение

Директиву, как и компонент, добавляют в imports и пишут атрибутом:

// src/app/todo-list/todo-list.ts
import { Component, inject } from '@angular/core';
import { Highlight } from '../highlight';
import { TodoStore } from '../todo-store';
 
@Component({
  selector: 'app-todo-list',
  imports: [Highlight],
  templateUrl: './todo-list.html',
})
export class TodoList {
  store = inject(TodoStore);
}
<!-- src/app/todo-list/todo-list.html -->
<ul>
  @for (todo of store.todos(); track todo.id) {
    <li appHighlight>{{ todo.title }}</li>
  }
</ul>

Все пункты списка получат светло-жёлтый фон.

Реакция на события

В host можно подписаться на события элемента. Подсвечивать будем только при наведении, а состояние хранить в сигнале:

// src/app/highlight.ts
import { Directive, signal } from '@angular/core';
 
@Directive({
  selector: '[appHighlight]',
  host: {
    '(mouseenter)': 'active.set(true)',
    '(mouseleave)': 'active.set(false)',
    '[style.backgroundColor]': "active() ? 'lightyellow' : ''",
  },
})
export class Highlight {
  active = signal(false);
}

Наведите мышь на задачу — строка подсветится, уберите — фон исчезнет.

Параметр директивы

Цвет удобно передавать через сам атрибут. Для этого входу дают псевдоним, совпадающий с селектором:

// src/app/highlight.ts
import { Directive, input, signal } from '@angular/core';
 
@Directive({
  selector: '[appHighlight]',
  host: {
    '(mouseenter)': 'active.set(true)',
    '(mouseleave)': 'active.set(false)',
    '[style.backgroundColor]': "active() ? (color() || 'lightyellow') : ''",
  },
})
export class Highlight {
  color = input('', { alias: 'appHighlight' });
  active = signal(false);
}
<!-- src/app/todo-list/todo-list.html -->
<li appHighlight="lightblue">{{ todo.title }}</li>
<li [appHighlight]="todo.done ? 'lightgreen' : 'pink'">{{ todo.title }}</li>

Без значения атрибута используется жёлтый цвет. Во второй строке выполненные задачи подсвечиваются зелёным, остальные — розовым.

Встроенные атрибутные директивы

В Angular есть готовые NgClass и NgStyle для набора классов и стилей. Сейчас вместо них обычно пишут привязки [class.имя] и [style.свойство] или [class] с объектом — о них урок о стилях.

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

Менять элемент напрямую через ElementRef и nativeElement.style. Это работает, но обходит Angular: такой код сложнее тестировать, и он не работает при серверном рендеринге. Для стилей, классов и событий используйте свойство host.

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

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