Angular offers two form models. Template-driven forms build the model from directives in the template, which is concise for simple cases. Reactive forms define the model in the component class, which scales for dynamic fields, complex validation and testability.
Before you start
You should be comfortable with ngModel and FormGroup. This article compares the models and helps you choose; it assumes basic form binding.
Step-by-step walkthrough
Step 1: Recognize where the model lives
Template-driven forms create the control tree from ngModel and name attributes, so the template is the source of truth and the model is synchronous. Reactive forms create the tree with FormControl and FormGroup in the class, so the model is explicit and available before the template renders.
Step 2: Match the model to the screen’s complexity
Template-driven suits short forms with simple validation, where brevity wins. Reactive suits forms with dynamic fields, cross-field rules, per-field async validation and unit tests, because the model can be built and tested without the DOM.
Step 3: Do not mix the two
Binding ngModel inside a FormGroup without [ngModelOptions]="{ standalone: true }" registers the control in the parent group and creates a second source of truth. Pick one model per control and, when embedding a template-driven field in a reactive form, mark it standalone deliberately.
Worked scenario
The reactive model is defined and tested in the class.
import { FormBuilder, Validators } from '@angular/forms';
export class LoginComponent {
private fb = new FormBuilder();
form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['', Validators.required],
});
submit(): void {
if (this.form.valid) {
// send this.form.value
}
}
}Walk through the example
The FormGroup exists as soon as the component is constructed, so the value and validity are available to test without rendering. Templates bind with formControlName, which reads and writes the same controls. The model is the class field, so a unit test can set values and assert validity directly.
Common mistake
Starting with ngModel and later adding cross-field validation, which forces a rewrite or awkward ngModelGroup usage. Another is mixing ngModel into a reactive group, producing duplicate controls and unpredictable values.
Verify the behavior
Unit-test the reactive form by setting values and asserting valid transitions. Add a dynamic FormArray and confirm it renders and validates. For a template-driven form, assert that the model updates after input and that required validation blocks submit.
Interview exercise
A checkout form grows from three fields to a dynamic list with cross-field rules. Which model fits?
Answer and reasoning
Reactive forms. Dynamic fields and cross-field validation are straightforward when the model is built in the class, with FormArray for the list and a group-level validator for the rules. Template-driven forms would need ngModelGroup gymnastics and are hard to unit-test, so the growth is the signal to switch.
Continue learning
Compare form ownership in Reactive form ownership and cross-field validation. Read the Angular forms overview and try the Angular interview questions.