Reactive Forms
13 min read
Reactive Forms
Reactive forms define the form structure in the TypeScript class using FormGroup and FormControl. Validation rules live in the class, not the template, making them easier to unit test and better for complex or dynamic form scenarios.
ts
import { Component, inject } from '@angular/core';
import {
ReactiveFormsModule,
FormBuilder,
Validators
} from '@angular/forms';
@Component({
selector: 'app-login',
standalone: true,
imports: [ReactiveFormsModule],
template: `
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div>
<label>Email</label>
<input formControlName="email" type="email" />
@if (form.get('email')?.invalid && form.get('email')?.touched) {
<span>Valid email required.</span>
}
</div>
<div>
<label>Password</label>
<input formControlName="password" type="password" />
@if (form.get('password')?.hasError('minlength')) {
<span>Password must be at least 8 characters.</span>
}
</div>
<button type="submit" [disabled]="form.invalid">Log In</button>
</form>
`
})
export class LoginComponent {
private fb = inject(FormBuilder);
form = this.fb.group({
email: ['', [Validators.required, Validators.email]],
password: ['', [Validators.required, Validators.minLength(8)]]
});
onSubmit() {
if (this.form.valid) {
console.log(this.form.value);
}
}
}Form Builder Shorthand
FormBuilder (injected via inject(FormBuilder)) provides a .group() shorthand to avoid writing new FormControl() for each field. You can also use .array() for dynamic lists of controls and .nonNullable.group() to ensure values are never null.
Use form.valueChanges (an Observable) to react to any form change in real time — perfect for live search, autosave, or dependent field logic.
Ready to test yourself?
Practice Angular— quiz & coding exercises