Choosing between reactive and template-driven forms helps you decide how to build and manage forms in Angular. Each way has its own style and benefits.
Reactive forms vs template forms decision in Angular
Template-driven form example: <form #myForm="ngForm" (ngSubmit)="onSubmit(myForm)"> <input name="email" ngModel required email /> <button type="submit">Submit</button> </form> Reactive form example: import { FormGroup, FormControl, Validators } from '@angular/forms'; myForm = new FormGroup({ email: new FormControl('', [Validators.required, Validators.email]) }); <form [formGroup]="myForm" (ngSubmit)="onSubmit()"> <input formControlName="email" /> <button type="submit">Submit</button> </form>
Template-driven forms use directives in HTML to create and manage forms.
Reactive forms use explicit form model objects in TypeScript for better control.
<form #formRef="ngForm"> <input name="username" ngModel required /> </form>
myForm = new FormGroup({ username: new FormControl('', Validators.required) }); <form [formGroup]="myForm"> <input formControlName="username" /> </form>
This Angular component shows both reactive and template-driven forms side by side. Each form has email and password fields with validation. The reactive form uses FormGroup and FormControl in TypeScript. The template-driven form uses ngModel and template references in HTML. Both forms disable the submit button until valid and show error messages when touched and invalid.
import { Component } from '@angular/core'; import { FormGroup, FormControl, Validators } from '@angular/forms'; @Component({ selector: 'app-login', template: ` <h2>Reactive Form Example</h2> <form [formGroup]="loginForm" (ngSubmit)="submit()"> <label for="email">Email:</label> <input id="email" formControlName="email" /> <div *ngIf="email.invalid && email.touched" style="color:red"> Email is required and must be valid. </div> <label for="password">Password:</label> <input id="password" type="password" formControlName="password" /> <div *ngIf="password.invalid && password.touched" style="color:red"> Password is required. </div> <button type="submit" [disabled]="loginForm.invalid">Login</button> </form> <h2>Template-driven Form Example</h2> <form #templateForm="ngForm" (ngSubmit)="submitTemplate(templateForm)"> <label for="email2">Email:</label> <input id="email2" name="email" ngModel required email #email2="ngModel" /> <div *ngIf="email2.invalid && email2.touched" style="color:red"> Email is required and must be valid. </div> <label for="password2">Password:</label> <input id="password2" name="password" type="password" ngModel required #password2="ngModel" /> <div *ngIf="password2.invalid && password2.touched" style="color:red"> Password is required. </div> <button type="submit" [disabled]="templateForm.invalid">Login</button> </form> ` }) export class LoginComponent { loginForm = new FormGroup({ email: new FormControl('', [Validators.required, Validators.email]), password: new FormControl('', Validators.required) }); get email() { return this.loginForm.get('email')!; } get password() { return this.loginForm.get('password')!; } submit() { if (this.loginForm.valid) { alert('Reactive form submitted: ' + JSON.stringify(this.loginForm.value)); } } submitTemplate(form: any) { if (form.valid) { alert('Template-driven form submitted: ' + JSON.stringify(form.value)); } } }
Reactive forms give you more power and flexibility for complex forms.
Template-driven forms are easier for simple forms and quick setups.
Both forms support validation and user feedback.
Reactive forms use explicit form models in TypeScript for control.
Template-driven forms use directives in HTML for simplicity.
Choose based on form complexity and your preference for code style.