Skip to content

Two-Way Binding with ngModel

Property binding ([property]) flows data into the DOM. Event binding ((event)) flows events out of the DOM. Two-way binding does both at once — it keeps a class property and a form input in sync. Angular provides this through [(ngModel)].

[(ngModel)] is shorthand for combining [ngModel] (property binding) and (ngModelChange) (event binding). The nickname “banana in a box” comes from the visual: [()].

<input [(ngModel)]="searchQuery" placeholder="Search movies..." />
<p>You typed: {{ searchQuery }}</p>
searchQuery = '';

As the user types, searchQuery is updated in real time. The displayed paragraph updates to match. Change searchQuery in the class (via a method or timer), and the input reflects the new value.

NgModel comes from @angular/forms. To use it, add FormsModule to the component’s imports array:

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-search',
standalone: true,
imports: [FormsModule],
template: `
<input [(ngModel)]="query" placeholder="Search..." />
<p>{{ query }}</p>
`
})
export class Search {
query = '';
}

Without FormsModule, Angular will not recognize [(ngModel)] and the template will not compile.

[(ngModel)] is part of Angular’s template-driven forms approach. It is simple and works well for basic inputs — a single search field, a toggle, a text input.

For more complex scenarios — multiple fields, validation, dynamic forms, debounced API calls — Angular’s reactive forms (covered in Module 06) are better. They give you a TypeScript object that represents the entire form, which is easier to validate and test.

In CinemaVault:

  • The NavBar search input uses [(ngModel)] — it is a single field that reads a query and navigates.
  • The Browse filter form uses reactive forms — it has multiple fields (genre, year, sort) that need to be watched together.

[(ngModel)]="prop" is exactly equivalent to:

<input [ngModel]="prop" (ngModelChange)="prop = $event" />

The [ngModel] sets the input’s value from prop. The (ngModelChange) event fires when the user changes the input and updates prop with the new value. The [()] syntax is syntactic sugar that writes this for you.

  1. Create a components/search-bar component with FormsModule in imports.
  2. Add a query = '' property.
  3. Add <input [(ngModel)]="query" placeholder="Search..." /> to the template.
  4. Display the current query below the input with <p>Searching for: {{ query }}</p>.
  5. Add a “Clear” button with (click)="query = ''" and confirm that clicking it clears both the input and the displayed text simultaneously.
  • [(ngModel)] is two-way binding — it keeps a class property and an input value in sync automatically.
  • It is shorthand for [ngModel]="prop" (ngModelChange)="prop = $event".
  • Add FormsModule to the component’s imports array to use NgModel.
  • Use [(ngModel)] for simple single-field inputs; use reactive forms (Module 06) for complex forms with validation and multiple fields.