Атрибутные директивы
Директива добавляет поведение к обычному элементу. Компонент — это директива с шаблоном, а атрибутная директива шаблона не имеет: её пишут как атрибут у любого тега, и она меняет вид или поведение этого тега. Например, подсветка строки при наведении мыши.
Создание директивы
ng generate directive highlightCLI создаст файл 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.