codejump

AcademyAngular

Two-Way Binding and Reactive Forms

[(ngModel)] is sugar over a property and event bound together; reactive forms trade that convenience for FormControl, validators and explicit state.

2 min readUpdated

3 exercises

Waiting at the end of this page.

[(ngModel)] is [value] and (event) fused into one syntax

The banana-in-a-box syntax is not a separate mechanism — it desugars to a property binding paired with an event binding on the same control:

HTML
<!-- these two lines do the same thing -->
<input [(ngModel)]="name" />
<input [value]="name" (input)="name = $event.target.value" />

A field that visually updates but never changes the component's own state is almost always the second form written by hand, incompletely: [value]="name" alone binds one-way, into the input, and without the matching (input) handler nothing ever flows back out. The same applies to a checkbox bound as [checked] with no (change) — it toggles on screen because the browser owns that visual state natively, while the component's boolean sits frozen at whatever it started as.

Reactive forms make every one of those steps explicit

FormControl, wired through [formControl] or formControlName, replaces the implicit two-way wiring with an object the component owns and can call .setValue(), .disable() or attach validators to directly:

typescript
email = new FormControl('', [Validators.required, Validators.email]);

An email field that "accepts anything" is usually a validator array that was declared but never actually attached to the control the template binds — the FormControl exists, the validators exist, but they were passed to a different instance, or the template still points at a plain ngModel-bound field instead of formControlName.

touched, dirty and disabled are three different questions

control.invalid alone is rarely what a submit button should check — showing an error message the instant a form loads, before anyone has typed anything, means the template checked invalid without also checking touched (has this field been focused and blurred) or dirty (has its value actually changed from the initial one). A submit button that "never disables" is frequently bound to [disabled]="control.invalid" when the control itself was never marked as required in the first place, so invalid never becomes true no matter what the user types.

What interviewers check

Whether you can explain [(ngModel)] as sugar rather than as its own primitive, and whether you reach for touched/dirty correctly when a reactive form's error state needs to distinguish "not filled in yet" from "filled in wrong."

Now practice it

1 quiz · 2 drills

Reading this page is the cheap half. These are the exercises that make you use it.