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.
keydownfires when a key goes down. It repeats while the key is held.keyupfires 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];
}
}
| Point | input | change |
|---|---|---|
| Text fields | Fires on every key press | Fires when the field loses focus |
<select>, checkbox, radio | Fires on selection | Fires on selection |
| Best for | Live feedback: counters, search-as-you-type | Committed 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:
| Event | Object type | Useful properties |
|---|---|---|
click | MouseEvent | clientX, clientY, ctrlKey, target |
keydown, keyup | KeyboardEvent | key, code, shiftKey, target |
input, change | Event | target (the element, with its value) |
submit | SubmitEvent | submitter, 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.
| Method | What it stops |
|---|---|
event.preventDefault() | The browser's default action: submit, navigation, context menu |
event.stopPropagation() | The event reaching parent elements' handlers |
Common Mistakes
| Mistake | What you see | Fix |
|---|---|---|
Missing parentheses: (click)="save" | Nothing happens on click | Call the method: (click)="save()" |
Reading $event.target.value in a TypeScript handler | Property 'value' does not exist on type 'EventTarget' | Cast: (event.target as HTMLInputElement).value |
Using change for live text feedback | The counter updates only after leaving the field | Use the input event |
Form submit without preventDefault() | The page reloads and loses its state | Call event.preventDefault(), or use (ngSubmit) |
(keyup.Enter) with a capital E | The handler never runs | Key names are lower case: (keyup.enter) |
Heavy work in a keydown handler | Typing feels slow | Keep 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
inputfor live feedback andchangefor committed values. Pass$eventor 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.