How to use two-way data binding in Angular
Two-way data binding is fundamental for creating reactive forms and synchronized user interfaces in Angular applications where data flows both from component to template and back. As the creator of CoreUI, a widely used open-source UI library, I’ve implemented two-way data binding in countless Angular form components, input controls, and interactive elements for enterprise applications. From my expertise, the most powerful approach is to use ngModel directive with the banana-in-a-box syntax. This method provides automatic synchronization between component properties and form inputs, eliminating the need for manual event handling in most scenarios.
Use [(ngModel)]
banana-in-a-box syntax for two-way data binding between component properties and form inputs.
import { Component } from '@angular/core'
import { FormsModule } from '@angular/forms'
@Component({
selector: 'app-user-form',
standalone: true,
imports: [FormsModule],
template: `
<form>
<div>
<label>Name:</label>
<input [(ngModel)]="user.name" name="name" type="text">
<p>Hello, {{ user.name }}!</p>
</div>
<div>
<label>Email:</label>
<input [(ngModel)]="user.email" name="email" type="email">
</div>
<div>
<label>Age:</label>
<input [(ngModel)]="user.age" name="age" type="number">
</div>
<div>
<label>Bio:</label>
<textarea [(ngModel)]="user.bio" name="bio"></textarea>
</div>
<div>
<label>
<input [(ngModel)]="user.subscribed" name="subscribed" type="checkbox">
Subscribe to newsletter
</label>
</div>
<div>
<h4>Current User Data:</h4>
<pre>{{ user | json }}</pre>
</div>
</form>
`
})
export class UserFormComponent {
user = {
name: '',
email: '',
age: null,
bio: '',
subscribed: false
}
}
The [(ngModel)]
syntax combines property binding [ngModel]
and event binding (ngModelChange)
into a single directive. When the input value changes, ngModel automatically updates the bound component property. When the component property changes programmatically, the input value updates to reflect the new state. This creates true two-way synchronization. The FormsModule
must be imported to use ngModel. Each form control should have a unique name
attribute for proper form handling.
Best Practice Note:
This is the same approach we use in CoreUI Angular form components for reactive user interfaces and data binding.
Import FormsModule
for template-driven forms or use ReactiveFormsModule
with formControlName
for reactive forms. Always provide name
attributes for form controls and consider validation with Angular’s built-in validators.