Event binding

Angular · Essentials · 9 min

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's host metadata, for example host: { '(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()".

Check yourself

  1. What is $event in (input)="onInput($event)" on an <input>?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: angular.dev/guide/templates/event-listeners