1. Введение
Event Binding — это механизм, который позволяет реагировать на действия пользователя (например, клик мышью, ввод текста, наведение курсора и т.д.) и вызывать методы вашего компонента. В Angular это делается с помощью простого и очень выразительного синтаксиса:
<button (click)="onClick()">Нажми меня!</button>
Здесь (click) — это событие DOM (в данном случае, клик по кнопке), а "onClick()" — вызов метода вашего компонента. Когда пользователь кликает на кнопку, Angular вызывает указанный метод.
Аналогия:
Если property binding ([property]) — это "отправка данных из компонента в DOM", то event binding ((event)) — это "получение сигналов из DOM в компонент".
Синтаксис Event Binding
Синтаксис очень прост:
<элемент (событие)="выражение">
- (событие) — имя DOM-события в круглых скобках (например, click, input, mouseover, keydown и т.д.).
- выражение — обычно это вызов метода вашего компонента, но может быть и простое выражение.
Примеры:
<button (click)="sayHello()">Сказать привет</button>
<input (input)="onInputChange($event)">
<div (mouseenter)="onMouseEnter()"></div>
Простой пример: обрабатываем клик
Давайте создадим простейший компонент, который считает, сколько раз нажали на кнопку.
counter.component.ts:
import { Component } from '@angular/core';
@Component({
selector: 'app-counter',
templateUrl: './counter.component.html'
})
export class CounterComponent {
count = 0;
increment() {
this.count++;
}
}
counter.component.html:
<button (click)="increment()">Увеличить</button>
<p>Вы нажали: {{ count }} раз(а)</p>
Пояснение:
- При каждом клике на кнопку вызывается метод increment(), который увеличивает счётчик.
- Значение count сразу отображается в шаблоне благодаря интерполяции.
2. Передача события ($event) в обработчик
Часто нужно узнать детали события: например, какой текст ввёл пользователь, какая клавиша была нажата и т.д. Для этого Angular автоматически передаёт объект события через переменную $event.
Пример: отслеживаем ввод в поле
input-logger.component.ts:
import { Component } from '@angular/core';
@Component({
selector: 'app-input-logger',
templateUrl: './input-logger.component.html'
})
export class InputLoggerComponent {
lastValue = '';
logInput(event: Event) {
const inputElement = event.target as HTMLInputElement;
this.lastValue = inputElement.value;
}
}
input-logger.component.html:
<input (input)="logInput($event)" placeholder="Печатайте здесь...">
<p>Последнее значение: {{ lastValue }}</p>
- (input) — событие, возникающее при изменении значения поля.
- В метод logInput автоматически передаётся объект события.
- Через event.target.value получаем текущее значение поля.
Важный момент:
Тип события всегда можно уточнить (например, KeyboardEvent, MouseEvent, FocusEvent), но чаще всего для простоты используют Event.
3. Event Binding и параметры: как передать свои значения
Иногда хочется передать в обработчик не только событие, но и какие-то свои данные. В Angular это делается просто:
<button (click)="addToCart(product)">В корзину</button>
Здесь мы передаём переменную product (например, объект товара) в метод компонента вместе с событием.
product-list.component.ts:
addToCart(product: Product) {
console.log('Добавлен в корзину:', product.name);
}
Если нужно передать и объект события, и свой параметр — порядок не важен:
<button (click)="doSomething($event, item)">Действие</button>
4. Популярные DOM-события в Angular
Вот самые часто используемые события:
| Событие | Где применяется | Когда срабатывает |
|---|---|---|
|
Кнопки, ссылки, любые | Пользователь кликает мышью |
|
<input>, <textarea> | Вводится/меняется текст |
|
<input>, <select> | Изменение значения (после потери фокуса) |
|
Любые элементы | Нажата клавиша |
|
Любые элементы | Отпущена клавиша |
|
Любые элементы | Курсор зашёл на элемент |
|
Любые элементы | Курсор покинул элемент |
|
<form> | Отправлена форма |
Пример: реагируем на нажатие Enter
<input (keydown.enter)="onEnter()">
.enter — это Angular-специфичный синтаксис для фильтрации по клавише (подробнее — ниже).
5. События с фильтрацией: (keydown.enter), (keyup.escape) и др.
Angular позволяет "слушать" не только событие, но и конкретную клавишу, используя так называемые event filtering.
Пример:
<input (keydown.enter)="sendMessage()">
keydown.enter — обработчик вызовется только если нажата клавиша Enter.
Поддерживаются такие фильтры:
enter, escape, tab, space, backspace, delete, arrowup, arrowdown, и др.
6. Пример: лайк-счетчик (развиваем приложение)
Давайте усложним пример с кнопкой. Добавим лайки и дизлайки с разными обработчиками событий.
like-dislike.component.ts:
import { Component } from '@angular/core';
@Component({
selector: 'app-like-dislike',
templateUrl: './like-dislike.component.html'
})
export class LikeDislikeComponent {
likes = 0;
dislikes = 0;
addLike() {
this.likes++;
}
addDislike() {
this.dislikes++;
}
}
like-dislike.component.html:
<button (click)="addLike()">👍 Лайк</button>
<button (click)="addDislike()">👎 Дизлайк</button>
<p>Лайков: {{ likes }} | Дизлайков: {{ dislikes }}</p>
Пояснение:
- У каждого события свой обработчик.
- Можно, конечно, сделать универсальный метод и передавать параметр, чтобы не копировать код.
7. Полезные нюансы
Inline-выражения в Event Binding
В выражении можно не только вызывать методы, но и выполнять простые операции:
<button (click)="count = count + 1">+1</button>
<button (click)="count = 0">Сбросить</button>
Но если логика становится сложнее — лучше выносить её в методы компонента! Помните: шаблон должен быть простым.
Обработка submit формы
Очень частый кейс — обработка отправки формы.
form-example.component.html:
<form (submit)="onSubmit($event)">
<input name="name" placeholder="Ваше имя">
<button type="submit">Отправить</button>
</form>
form-example.component.ts:
onSubmit(event: Event) {
event.preventDefault(); // Останавливаем стандартную отправку
// Дальше обрабатываем данные формы
}
Пояснение:
- Без event.preventDefault() страница бы перезагрузилась — стандартное поведение формы.
- Обычно в Angular используют ngSubmit вместо обычного submit, особенно с Angular-формами, но про это — в следующих лекциях.
Несколько событий на одном элементе
Можно навесить сколько угодно обработчиков разных событий:
<button
(mouseenter)="onHover()"
(mouseleave)="onLeave()"
(click)="onClick()"
>
Наведи и кликни
</button>
Event Binding и this
Важный момент: В обработчиках событий this всегда ссылается на ваш компонент, а не на DOM-элемент! Это гарантируется Angular. Не нужно делать никаких .bind(this) (как в React-классах).
События и bubbling (всплытие)
Angular не отменяет стандартное поведение событий DOM: если событие всплывает, оно всплывает. Вы можете остановить всплытие вручную в обработчике:
onClick(event: MouseEvent) {
event.stopPropagation();
}
Property Binding vs Event Binding
| Связывание | Синтаксис | Направление данных | Пример |
|---|---|---|---|
| Property Binding | |
Компонент → DOM | |
| Event Binding | |
DOM → Компонент | |
8. Типичные ошибки при Event Binding
Ошибка №1: Описка в названии события.
Например, написали (clic) вместо (click). Angular просто проигнорирует, и обработчик не сработает. Проверьте, что событие называется правильно!
Ошибка №2: Забытая пара скобок.
Иногда пишут click="doSmth()" вместо (click)="doSmth()". В результате Angular воспримет это как обычный HTML-атрибут, а не как обработчик события.
Ошибка №3: Вызов несуществующего метода.
Если в шаблоне написано (click)="nonExistent()", а такого метода нет в компоненте — будет ошибка в консоли.
Ошибка №4: Использование переменных, не определённых в компоненте.
Если вы передаёте что-то типа (click)="addToCart(product)", но переменной product в шаблоне или компоненте нет — будет ошибка.
Ошибка №5: Забытая обработка $event.
Если вы хотите получить данные из события ((input)="onInput($event)"), но не принимаете параметр в методе — будет undefined.
Ошибка №6: Сложная логика прямо в шаблоне.
Иногда хочется написать (click)="count > 5 ? reset() : increment()". Лучше выносить сложные условия в методы компонента.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ