Angular Reactive Forms

Angular Reactive Forms

Reactive Forms provide a model-driven approach to handling form inputs — the form structure is defined in the component class, making it easier to test, validate, and manipulate dynamically.

Setup

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

@Component({
  selector: 'app-register',
  standalone: true,
  imports: [ReactiveFormsModule],
  templateUrl: './register.component.html',
})
export class RegisterComponent {
  private fb = inject(FormBuilder);

  form = this.fb.group({
    name:     ['', [Validators.required, Validators.minLength(2)]],
    email:    ['', [Validators.required, Validators.email]],
    password: ['', [Validators.required, Validators.minLength(8)]],
    role:     ['user', Validators.required],
    agree:    [false, Validators.requiredTrue],
  });

  get name()     { return this.form.get('name')! }
  get email()    { return this.form.get('email')! }
  get password() { return this.form.get('password')! }

  onSubmit(): void {
    if (this.form.invalid) { this.form.markAllAsTouched(); return; }
    console.log(this.form.value);
  }
}

Template

<form [formGroup]="form" (ngSubmit)="onSubmit()">

  <input formControlName="name" placeholder="Full name" />
  @if (name.invalid && name.touched) {
    <span class="error">
      @if (name.errors?.['required'])  { Name is required. }
      @if (name.errors?.['minlength']) { At least 2 characters. }
    </span>
  }

  <input formControlName="email" type="email" />
  @if (email.invalid && email.touched) {
    <span class="error">Valid email required.</span>
  }

  <button type="submit" [disabled]="form.invalid">Register</button>

</form>