Event Handling in Angular

By Syncfusion®, Inc. · Last updated

How Angular handles click, keyboard, input and change events, reading the event object, passing parameters to handlers, and preventing the browser's default behavior.

Introduction to Events

An event is a signal the browser sends when something happens on the page, such as a click, a key press or a change to a form field. Event handling is the code that runs in response.

In Angular, the template listens for an event and calls a method in the component class. The method updates the class data, and Angular updates the page.

Real-World Example

On a checkout page, clicking Apply validates a coupon code, pressing Enter in the address field moves focus to the next field, and changing the delivery option recalculates the total.

Submitting the form must not reload the page, so the handler stops the browser's default submit and sends the order to the API instead.

User actionclick, key, change(event)event bindingHandlerclass methodDataclass propertyViewupdated page

An event runs a method. The method changes data. Angular updates the page.

Event Binding Review

You listen for an event with event binding: the event name in round brackets, followed by a template statement.

<button (click)="save()">Save</button>
  • (click) is the event to listen for.
  • save() is the statement Angular runs when the event fires. It usually calls a method of the component class.

Angular supports every standard DOM event this way, such as click, dblclick, keydown, keyup, input, change, focus, blur and submit.

Click Events

The click event fires when the user presses and releases the mouse button on an element, or presses Enter or Space on a focused button. It is the most common event in any app.

Click events update a shopping cart

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <p>Cart: {{ quantity }} item(s) · ₹{{ quantity * price }}</p>
    <button (click)="increase()">+ Add</button>
    <button (click)="decrease()" [disabled]="quantity === 0">− Remove</button>
    <button (dblclick)="quantity = 0">Double-click to empty</button>
  `,
})
export class App {
  quantity = 1;
  price = 799;

  increase() {
    this.quantity++;
  }

  decrease() {
    if (this.quantity > 0) this.quantity--;
  }
}

The third button listens for dblclick, which fires only after two quick clicks.

Keyboard Events

Keyboard events fire when the user presses keys while an element has focus.

Key presseda, b, Enter(keyup.enter)Angular checks the keyOnly Enterother keys stop heresearch()your method runsAngular calls the method only for the key you name in the event.

A key filter such as keyup.enter calls the method only for that key.

  • keydown fires when a key goes down. It repeats while the key is held.
  • keyup fires when the key is released.

Angular adds key event filters. (keyup.enter) runs only for the Enter key, and (keydown.escape) runs only for Escape. You can combine modifier keys: (keydown.control.s).

Key filters run code only for specific keys

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <input #box placeholder="Search products" (keyup.enter)="search(box.value)" (keydown.escape)="box.value = ''; result = 'Search cleared'" />
    <p>{{ result }}</p>
  `,
})
export class App {
  result = 'Type a word and press Enter. Press Escape to clear.';

  search(term: string) {
    this.result = term ? 'Searching for "' + term + '"…' : 'Enter a search term first.';
  }
}

Key filter names are the browser's KeyboardEvent.key values in lower case, such as enter, escape, tab, space, arrowup and arrowdown. Modifier keys come first: (keydown.shift.enter).

Input Events

The input event fires on every change to the value of an <input> or <textarea>, including typing, pasting and deleting. Use it for live feedback, such as a character counter.

The input event updates a counter on every key press

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <textarea rows="3" cols="40" maxlength="140" (input)="onInput($event)"></textarea>
    <p [style.color]="remaining < 20 ? '#dc2626' : '#374151'">{{ remaining }} characters left</p>
  `,
})
export class App {
  limit = 140;
  remaining = 140;

  onInput(event: Event) {
    const text = (event.target as HTMLTextAreaElement).value;
    this.remaining = this.limit - text.length;
  }
}

Change Events

The change event fires when the user commits a change. The timing depends on the element:

  • For <select>, checkboxes and radio buttons, it fires as soon as the selection changes.
  • For text inputs, it fires only when the field loses focus after its value changed.

Change events recalculate the delivery cost

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <label>Delivery:
      <select (change)="setDelivery($event)">
        <option value="standard">Standard (₹0)</option>
        <option value="express">Express (₹99)</option>
        <option value="sameday">Same day (₹199)</option>
      </select>
    </label>
    <p><label><input type="checkbox" (change)="giftWrap = !giftWrap" /> Gift wrap (₹49)</label></p>
    <p>Order total: ₹{{ subtotal + deliveryCost + (giftWrap ? 49 : 0) }}</p>
  `,
})
export class App {
  subtotal = 1200;
  deliveryCost = 0;
  giftWrap = false;
  costs: Record<string, number> = { standard: 0, express: 99, sameday: 199 };

  setDelivery(event: Event) {
    const choice = (event.target as HTMLSelectElement).value;
    this.deliveryCost = this.costs[choice];
  }
}
Pointinputchange
Text fieldsFires on every key pressFires when the field loses focus
<select>, checkbox, radioFires on selectionFires on selection
Best forLive feedback: counters, search-as-you-typeCommitted values: filters, settings, totals

Event Objects ($event)

$event is a special variable in an event binding. It contains the event object that the browser creates for the event.

Browsercreates the event$eventtype, key, targetonInput($event)template passes ittarget.valuethe method reads it$event carries details about what happened: the element, the key, the text.

$event moves the event details from the template to your method.

The type of the object depends on the event:

EventObject typeUseful properties
clickMouseEventclientX, clientY, ctrlKey, target
keydown, keyupKeyboardEventkey, code, shiftKey, target
input, changeEventtarget (the element, with its value)
submitSubmitEventsubmitter, target

$event gives the handler details about the event

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <input placeholder="Press any key" (keydown)="onKey($event)" />
    <p>{{ lastKey }}</p>
    <button (click)="onClick($event)">Click me (try with Ctrl or Shift)</button>
    <p>{{ lastClick }}</p>
  `,
})
export class App {
  lastKey = 'No key pressed yet';
  lastClick = 'No click yet';

  onKey(event: KeyboardEvent) {
    this.lastKey = 'Key: ' + event.key + ' (code: ' + event.code + ')';
  }

  onClick(event: MouseEvent) {
    this.lastClick = event.ctrlKey ? 'Clicked with Ctrl' : event.shiftKey ? 'Clicked with Shift' : 'Normal click';
  }
}

event.target is typed as a general EventTarget. To read value, tell TypeScript the element type: (event.target as HTMLInputElement).value.

Passing Parameters to Event Handlers

A handler can receive any values from the template, not only $event. You pass them as normal method arguments: (click)="select(plan)".

This is how one method serves many elements, such as a list where each row has its own Delete button.

Each button passes its own item to the same method

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <ul>
      @for (file of files; track file; let i = $index) {
        <li>{{ file }} <button (click)="remove(i, file)">Delete</button></li>
      }
    </ul>
    <p>{{ message }}</p>
  `,
})
export class App {
  files = ['report.pdf', 'invoice.xlsx', 'logo.png'];
  message = '';

  remove(index: number, name: string) {
    this.files.splice(index, 1);
    this.message = 'Deleted ' + name;
  }
}

You can pass both your own values and the event: (click)="remove(i, file, $event)".

Preventing Default Behavior

Many elements have a default behavior that the browser runs after the event. A form submit reloads the page, a link click opens a new address, and a right-click opens the context menu.

Without preventDefault()With preventDefault()Submit clickedBrowser sends the formdefault behaviorPage reloadsdata on screen is lostSubmit clickedevent.preventDefault()default is stoppedYour code runspage stays

preventDefault() stops the browser action, so only your code runs.

Call event.preventDefault() in the handler to stop the default behavior. Your own code still runs.

preventDefault keeps the form submit inside Angular

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <form (submit)="onSubmit($event)">
      <input name="email" placeholder="Email" value="asha@example.com" />
      <button type="submit">Subscribe</button>
    </form>
    <p><a href="https://angular.dev" (click)="onLink($event)">Read the docs</a></p>
    <p>{{ status }}</p>
  `,
})
export class App {
  status = 'Nothing submitted yet';

  onSubmit(event: SubmitEvent) {
    event.preventDefault();
    this.status = 'Subscribed without reloading the page';
  }

  onLink(event: MouseEvent) {
    event.preventDefault();
    this.status = 'Link click handled by Angular';
  }
}

Click Subscribe and the link. The page stays in place and the status updates.

In real forms, Angular's forms package provides (ngSubmit), which prevents the page reload for you. You will use it in the Forms chapter.

MethodWhat it stops
event.preventDefault()The browser's default action: submit, navigation, context menu
event.stopPropagation()The event reaching parent elements' handlers

Common Mistakes

MistakeWhat you seeFix
Missing parentheses: (click)="save"Nothing happens on clickCall the method: (click)="save()"
Reading $event.target.value in a TypeScript handlerProperty 'value' does not exist on type 'EventTarget'Cast: (event.target as HTMLInputElement).value
Using change for live text feedbackThe counter updates only after leaving the fieldUse the input event
Form submit without preventDefault()The page reloads and loses its stateCall event.preventDefault(), or use (ngSubmit)
(keyup.Enter) with a capital EThe handler never runsKey names are lower case: (keyup.enter)
Heavy work in a keydown handlerTyping feels slowKeep handlers short, or react on keyup.enter

Check Yourself

Exercises

What to Remember

  • Listen for events with (event)="handler()", and use key filters such as (keyup.enter) for specific keys.
  • Use input for live feedback and change for committed values. Pass $event or your own values to the handler.
  • Call event.preventDefault() to stop the browser's default action, such as a page reload on submit.

Next: Component Communication, how parent and child components send data and events to each other.