Template-Driven Forms
Angular offers two distinct approaches to building forms: template-driven and reactive. Template-driven forms, enabled by importing FormsModule, let you define most of the form's structure, bindings, and validation directly in the HTML template using directives such as ngModel, ngForm, and validation attributes like required and minlength. Angular automatically creates and manages an underlying form model (instances of NgModel, NgForm) behind the scenes based on what it finds in the template, which makes this style fast to write for simple forms but harder to unit test and less scalable for complex, dynamic, or highly validated forms compared to the reactive approach.
Cricket analogy: Template-driven forms are like a club match run entirely by the on-field captain's calls (the template), fast to organize for a casual game with FormsModule as the rulebook, but harder to formally scrutinize afterward than a fully documented reactive scorecard used in first-class cricket.
ngModel and Two-Way Binding
The core building block is [(ngModel)], Angular's banana-in-a-box syntax for two-way data binding, which keeps a template input element's value synchronized with a component property in both directions: typing in the field updates the property, and programmatically changing the property updates the field. Each ngModel-bound control must have a name attribute so Angular can register it with the enclosing NgForm instance, which aggregates every control's value and validity into a single form-level model.
Cricket analogy: [(ngModel)]'s two-way binding is like a live scoreboard synced both ways with the official scorebook: update the paper scorebook and the digital board changes, update the digital board and the scorebook reflects it, with each player's name tag registering them into the team sheet (NgForm).
import { Component } from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms';
interface SignupModel {
email: string;
password: string;
}
@Component({
selector: 'app-signup',
standalone: true,
imports: [FormsModule],
template: `
<form #signupForm="ngForm" (ngSubmit)="onSubmit(signupForm)">
<label>
Email
<input name="email" type="email" required email [(ngModel)]="model.email" #email="ngModel" />
</label>
@if (email.invalid && email.touched) {
<p class="error">A valid email is required.</p>
}
<label>
Password
<input name="password" type="password" required minlength="8" [(ngModel)]="model.password" />
</label>
<button type="submit" [disabled]="signupForm.invalid">Sign up</button>
</form>
`,
})
export class SignupComponent {
model: SignupModel = { email: '', password: '' };
onSubmit(form: NgForm): void {
if (form.valid) {
console.log('Submitting', this.model);
}
}
}Validation and Form State
Validation in template-driven forms is declared using HTML validation attributes (required, minlength, maxlength, pattern, plus Angular's own email directive), which Angular translates into validator functions internally. Each control exposes state via CSS classes (ng-valid, ng-invalid, ng-touched, ng-pristine, ng-dirty) that you can style directly, and via a template reference variable (e.g. #email="ngModel") that exposes properties like .invalid, .touched, and .errors for conditional messages in the template.
Cricket analogy: HTML validation attributes like required and minlength are like standard playing-condition rules written directly into the match regulations, with CSS classes like ng-invalid acting as a visible red card flag and a template reference variable like #email letting the scorer directly query a specific player's disciplinary status.
Template-driven forms are conceptually similar to how plain HTML forms or Vue's v-model work — binding is declared inline in markup — whereas Angular's reactive forms are closer to explicitly building a form model in code, similar to libraries like React Hook Form or Formik that construct the form's shape and validators in JavaScript/TypeScript rather than markup.
Because the form model in a template-driven form is built asynchronously by Angular as it processes the template, ngModel-related properties like signupForm.value are not reliably available inside ngOnInit — code that needs the form's initial state should instead react to it via the (ngSubmit) handler or subscribe to NgForm.valueChanges after the view has initialized.
- Template-driven forms use
[(ngModel)]and live mostly in the HTML template, requiring FormsModule to be imported. - Every ngModel-bound control needs a unique
nameattribute so it registers with the parent NgForm. - Validation is declared via HTML attributes like
required,minlength, and Angular'semaildirective. - Form and control state (valid, touched, pristine, etc.) is exposed both as CSS classes and via template reference variables.
- The underlying form model is built asynchronously by Angular, so it isn't reliably accessible in ngOnInit.
- Template-driven forms suit simple forms; complex, dynamic, or heavily tested forms usually favor reactive forms instead.
Practice what you learned
1. Which module must be imported to use template-driven forms with ngModel?
2. What is required on each ngModel-bound input for it to register with the enclosing NgForm?
3. How is required-field validation typically expressed in a template-driven form?
4. Why is it unreliable to read a template-driven form's value inside ngOnInit?
5. Which CSS classes does Angular automatically apply to reflect a template-driven control's state?
Was this page helpful?
You May Also Like
Reactive Forms Basics
Learn Angular's reactive forms approach, where the form model is constructed explicitly in TypeScript with FormControl, FormGroup, and FormBuilder for more predictable, testable forms.
Form Validation and Custom Validators
Learn how Angular validates reactive forms with built-in validators, synchronous and asynchronous custom validators, and cross-field validation strategies.
Dynamic and Nested Form Groups
Build complex forms by nesting FormGroups and using FormArray to add, remove, and validate repeating or conditional sets of controls at runtime.
Template Syntax and Interpolation
How Angular templates blend HTML with expressions, and how interpolation renders component state directly into the DOM as text.
Related Reading
Related Study Notes in Web Development
Browse all study notesWebSockets Study Notes
Web Development · 30 topics
Web DevelopmentWebAssembly Study Notes
WebAssembly · 30 topics
Web DevelopmentgRPC Study Notes
Protocol Buffers · 30 topics
Web DevelopmentSpring Boot Study Notes
Java · 30 topics
Web DevelopmentFlask Study Notes
Python · 30 topics
Web DevelopmentDjango Study Notes
Python · 30 topics