Every interactive feature starts with an event handler.
Event binding uses parentheses: (click)="save()". When the event fires, Angular evaluates the statement, usually a method call on the component.
- Pass the native event with `$event`:
(input)="onInput($event)". Type it in the method and read the target:(event.target as HTMLInputElement).value. - Statements can be simple assignments or calls:
(click)="count.set(count() + 1)". Keep logic in methods; templates should stay declarative. - Key filters:
(keyup.enter)="send()",(keydown.escape)="close()", combinations like(keydown.control.s)="save($event)". - Any DOM event works, including custom events dispatched by web components, and component outputs use the same syntax.
- Global targets:
(window:resize)and(document:keydown)are available through the component'shostmetadata, for examplehost: { '(window:resize)': 'onResize()' }.
Call event.preventDefault() in your handler to stop default behaviour like following a link.
In zoneless apps, a template event handler is one of the things that tells Angular to run change detection, so updating a plain field inside it still refreshes the view. Updating state from timers or promises should go through signals, which notify Angular themselves. Making all template state signals is the simplest rule.
Example
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-chat-input',
template: `
<input [value]="draft()" (input)="onInput($event)"
(keyup.enter)="send()" (keydown.escape)="draft.set('')" />
<button (click)="send()" [disabled]="!draft()">Send</button>
@for (m of messages(); track $index) { <p>{{ m }}</p> }
`,
})
export class ChatInput {
protected draft = signal('');
protected messages = signal<string[]>([]);
protected onInput(event: Event) {
this.draft.set((event.target as HTMLInputElement).value);
}
protected send() {
if (!this.draft().trim()) return;
this.messages.update((list) => [...list, this.draft()]);
this.draft.set('');
}
}Remember
(event)="handler($event)"binds DOM events and component outputs- Key filters like
(keyup.enter)avoid manual key checks - Keep template statements to a single method call
Watch out for
- Forgetting to call the method:
(click)="save"does nothing; write(click)="save()".