Reactive Forms

Build the Form Model in TypeScript

Reactive Forms

Define FormControl, FormGroup, and FormArray in the class. The template binds to that model with formControlName and formGroup.

4 min read Level 2/5 #angular#forms#reactive
What you'll learn
  • Create a FormGroup with FormControls
  • Bind controls in the template
  • Read and write values from code

Reactive forms put the form definition in code. That gives you typed values, testable logic, and easy dynamism.

The Manual Way

import { Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="form" (ngSubmit)="save()">
      <input formControlName="email" placeholder="Email" />
      <input formControlName="password" type="password" />
      <button>Sign in</button>
    </form>
  `,
})
export class LoginComponent {
  form = new FormGroup({
    email: new FormControl(''),
    password: new FormControl(''),
  });

  save() {
    console.log(this.form.value);
  }
}

With FormBuilder

FormBuilder is a service that makes the construction terser.

import { Component, inject } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';

@Component({
  selector: 'app-login',
  standalone: true,
  imports: [ReactiveFormsModule],
  template: `<form [formGroup]="form">...</form>`,
})
export class LoginComponent {
  private fb = inject(FormBuilder);

  form = this.fb.group({
    email: ['', [Validators.required, Validators.email]],
    password: ['', [Validators.required, Validators.minLength(8)]],
  });
}

Reading and Writing

  • form.value — current data object
  • form.valid / form.invalid
  • form.controls.email — the individual control
  • form.patchValue({ email: 'a@b.com' }) — update some fields
  • form.setValue({...}) — update all fields, type-checked
  • form.reset() — back to initial state
  • form.valueChanges — observable of every change

The reactive API stays out of the DOM. You can test a form by instantiating its class and asserting on form.value — no fixtures needed.

Built-In Validators →