Question
In Angular 2 with TypeScript, how can you access the newly selected value from a <select> element?
In the following example, the onChange() handler is called when the selection changes, but this.selectedDevice appears to contain the previous value instead of the newly selected one:
<select [(ngModel)]="selectedDevice" (change)="onChange($event)">
<option *ngFor="let i of devices">{{ i }}</option>
</select>
onChange($event: Event) {
console.log(this.selectedDevice);
// I want to work with the newly selected device here,
// but this logs the previous selection instead.
}
How do you get the current selected value when the user chooses a new option?
Short Answer
By the end of this page, you will understand why a native (change) event can feel out of sync with Angular's two-way binding, and how to correctly get the new selected value from a <select> using ngModelChange, template references, or the event target.
Concept
In Angular forms, a <select> can be connected to a component property using [(ngModel)]. This is called two-way binding.
<select [(ngModel)]="selectedDevice">
This means:
- Angular writes the component value into the
<select> - Angular updates the component property when the user picks a new option
The confusion usually comes from mixing:
- the native DOM
(change)event - Angular's
[(ngModel)] - Angular's
(ngModelChange)event
Why this matters
When you use (change), you are listening to the browser's native event from the <select> element. That event gives you access to the DOM event object, but depending on how you read your component property, it may not yet look updated in the way you expect.
Angular also provides (ngModelChange), which is specifically designed to work with ngModel. It emits the new value directly.
The key idea
Mental Model
Think of a <select> as a form control with two messengers:
- The browser messenger says: "The user changed something in the DOM."
- The Angular messenger says: "The model value is now this new value."
If you listen to the browser messenger with (change), you may need to manually read the value from the event target.
If you listen to the Angular messenger with (ngModelChange), Angular hands you the updated value directly.
So:
(change)= "something changed in the element"(ngModelChange)= "here is the new model value"
That is why (ngModelChange) is often easier when using [(ngModel)].
Syntax and Examples
Recommended syntax: ngModelChange
<select [(ngModel)]="selectedDevice" (ngModelChange)="onChange($event)">
<option *ngFor="let device of devices" [value]="device">{{ device }}</option>
</select>
selectedDevice = '';
devices = ['Phone', 'Tablet', 'Laptop'];
onChange(newDevice: string) {
console.log('New selection:', newDevice);
console.log('Component property:', this.selectedDevice);
}
Why this works
[(ngModel)]="selectedDevice"keeps the component property in sync(ngModelChange)passes the new selected value as
Step by Step Execution
Consider this example:
<select [(ngModel)]="selectedDevice" (ngModelChange)="onChange($event)">
<option *ngFor="let device of devices" [value]="device">{{ device }}</option>
</select>
devices = ['Phone', 'Tablet', 'Laptop'];
selectedDevice = 'Phone';
onChange(newDevice: string) {
console.log('Selected:', newDevice);
}
What happens step by step
selectedDevicestarts as'Phone'- Angular shows
'Phone'as the selected option - The user changes the selection to
'Laptop' - Angular detects the form control update
ngModelupdates to
Real World Use Cases
This pattern is useful anywhere a dropdown controls app behavior.
Common examples
- Filtering data
- Select a category and reload a product list
- Choosing a device or environment
- Update a settings panel based on the selected option
- Sorting results
- Change from
NewesttoPrice: Low to High
- Change from
- Admin dashboards
- Select a user role, status, or region
- Forms
- Choose a country, payment method, or shipping option
Example: filter a list
<select [(ngModel)]="selectedCategory" (ngModelChange)="filterProducts($event)">
<option *ngFor="let category of categories" [value]="category">{{ category }}</option>
</select>
filterProducts(: ) {
.(, category);
}
Real Codebase Usage
In real Angular projects, developers usually prefer patterns that make state changes explicit and easy to read.
Common patterns
1. Use ngModelChange when you need the new value immediately
<select [(ngModel)]="status" (ngModelChange)="updateStatus($event)">
This is clear and works well for simple forms.
2. Use guard clauses
If a value is empty or invalid, exit early.
updateStatus(status: string) {
if (!status) {
return;
}
console.log('Updating status to', status);
}
3. Validate before acting
updateDevice(device: string) {
if (!this.devices.includes(device)) {
console.error();
;
}
. = device;
}
Common Mistakes
1. Expecting $event from (change) to be the selected value
Broken assumption:
<select (change)="onChange($event)"></select>
onChange(value: string) {
console.log(value); // This is not the selected string value
}
$event here is a DOM event object, not the selected option string.
Fix:
onChange(event: Event) {
const value = (event.target as HTMLSelectElement).value;
console.log(value);
}
Or use:
(ngModelChange)="onChange($event)"
Comparisons
| Approach | What it gives you | Best use case | Example |
|---|---|---|---|
(change) | DOM event object | When you need low-level event details | (change)="onChange($event)" |
(ngModelChange) | New bound value | When using [(ngModel)] and you want the updated selection | (ngModelChange)="onChange($event)" |
| Template reference variable | Direct element value | Simple templates where you want explicit control | (change)="onChange(selectRef.value)" |
change vs ngModelChange
Cheat Sheet
<!-- Best choice when using ngModel -->
<select [(ngModel)]="selectedValue" (ngModelChange)="onChange($event)">
<option *ngFor="let item of items" [value]="item">{{ item }}</option>
</select>
onChange(value: string) {
console.log(value);
}
Native change event
<select (change)="onChange($event)">
onChange(event: Event) {
const value = (event.target as HTMLSelectElement).value;
}
Template reference variable
FAQ
Why does Angular (change) give me the old value?
Because (change) is a native DOM event, not Angular's model-change event. If you need the new bound value directly, use (ngModelChange).
What is the difference between change and ngModelChange in Angular?
change comes from the browser and gives an event object. ngModelChange comes from Angular forms and gives the new model value.
How do I get the selected option value from a select in Angular?
The simplest way is:
<select [(ngModel)]="selectedValue" (ngModelChange)="onChange($event)">
Can I still use (change) with ngModel?
Yes. You just need to read the value from the event target:
const value = (event.target as HTMLSelectElement).;
Mini Project
Description
Build a small device selector component that lets a user choose a device from a dropdown and immediately displays a message showing the current selection. This demonstrates how to capture the newly selected value correctly in Angular using ngModelChange.
Goal
Create a dropdown that updates the component state and displays the newly selected device as soon as the user changes it.
Requirements
- Create a list of device names in the component
- Bind the select element to a component property using
ngModel - Call a method whenever the selection changes
- Show the currently selected device below the dropdown
- Use the newly selected value inside the event handler
Keep learning
Related questions
@Directive vs @Component in Angular: Differences, Use Cases, and When to Use Each
Learn the difference between @Directive and @Component in Angular, including use cases, examples, and when to choose each.
Angular (change) vs (ngModelChange): What’s the Difference?
Learn the difference between Angular (change) and (ngModelChange), when each fires, and which one to use in forms and inputs.
Angular Dependency Injection: Fix "Can't Resolve All Parameters for Component" Errors
Learn why Angular shows "Can't resolve all parameters for component" and how to fix service injection issues in components.