Swiftorial Logo
Home
Swift Lessons
Matchups
CodeSnaps
Tutorials
Career
Resources

Reactive Forms in Angular

Reactive forms in Angular provide a model-driven approach to handling form inputs and validations. This tutorial covers the basics of reactive forms and how to use them effectively in your Angular applications.

What are Reactive Forms?

Reactive forms are highly scalable and reusable forms built using a model-driven approach. They provide more control over the form's state and validations through the use of Angular's FormControl, FormGroup, and FormArray classes.

Setting Up Reactive Forms

To set up reactive forms, you need to import the ReactiveFormsModule in your application module:

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, ReactiveFormsModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Creating a Reactive Form

Here is an example of a simple reactive form:

// app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  userForm = new FormGroup({
    name: new FormControl('', [Validators.required]),
    email: new FormControl('', [Validators.required, Validators.email])
  });

  onSubmit() {
    console.log('Form submitted!', this.userForm.value);
  }
}

// app.component.html
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
  <div>
    <label for="name">Name</label>
    <input type="text" id="name" formControlName="name">
    <div *ngIf="userForm.get('name').invalid && userForm.get('name').touched">Name is required</div>
  </div>
  <div>
    <label for="email">Email</label>
    <input type="email" id="email" formControlName="email">
    <div *ngIf="userForm.get('email').invalid && userForm.get('email').touched">Enter a valid email</div>
  </div>
  <button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>

Form Validation

Reactive forms support built-in validators such as required, minlength, maxlength, pattern, etc. Custom validators can also be created if needed:

// app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  userForm = new FormGroup({
    name: new FormControl('', [Validators.required, Validators.minLength(3)]),
    email: new FormControl('', [Validators.required, Validators.email])
  });

  onSubmit() {
    console.log('Form submitted!', this.userForm.value);
  }
}

// app.component.html
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
  <div>
    <label for="name">Name</label>
    <input type="text" id="name" formControlName="name">
    <div *ngIf="userForm.get('name').invalid && userForm.get('name').touched">
      <div *ngIf="userForm.get('name').errors.required">Name is required</div>
      <div *ngIf="userForm.get('name').errors.minlength">Name must be at least 3 characters long</div>
    </div>
  </div>
  <div>
    <label for="email">Email</label>
    <input type="email" id="email" formControlName="email">
    <div *ngIf="userForm.get('email').invalid && userForm.get('email').touched">
      <div *ngIf="userForm.get('email').errors.required">Email is required</div>
      <div *ngIf="userForm.get('email').errors.email">Invalid email format</div>
    </div>
  </div>
  <button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>

Form Groups and Form Arrays

Reactive forms allow you to group controls together using FormGroup and FormArray for managing complex forms:

// app.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl, FormArray, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  userForm = new FormGroup({
    name: new FormControl('', [Validators.required]),
    email: new FormControl('', [Validators.required, Validators.email]),
    addresses: new FormArray([
      new FormGroup({
        street: new FormControl(''),
        city: new FormControl(''),
        state: new FormControl('')
      })
    ])
  });

  get addresses() {
    return (this.userForm.get('addresses') as FormArray).controls;
  }

  addAddress() {
    const addressForm = new FormGroup({
      street: new FormControl(''),
      city: new FormControl(''),
      state: new FormControl('')
    });
    (this.userForm.get('addresses') as FormArray).push(addressForm);
  }

  onSubmit() {
    console.log('Form submitted!', this.userForm.value);
  }
}

// app.component.html
<form [formGroup]="userForm" (ngSubmit)="onSubmit()">
  <div>
    <label for="name">Name</label>
    <input type="text" id="name" formControlName="name">
    <div *ngIf="userForm.get('name').invalid && userForm.get('name').touched">Name is required</div>
  </div>
  <div>
    <label for="email">Email</label>
    <input type="email" id="email" formControlName="email">
    <div *ngIf="userForm.get('email').invalid && userForm.get('email').touched">Email is required</div>
  </div>
  <div formArrayName="addresses">
    <div *ngFor="let address of addresses; let i = index" [formGroupName]="i">
      <h4>Address {{ i + 1 }}</h4>
      <label for="street">Street</label>
      <input type="text" formControlName="street">
      <label for="city">City</label>
      <input type="text" formControlName="city">
      <label for="state">State</label>
      <input type="text" formControlName="state">
    </div>
  </div>
  <button type="button" (click)="addAddress()">Add Address</button>
  <button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>

Key Points

  • Reactive forms are built using a model-driven approach and provide more control over the form's state and validations.
  • Use the ReactiveFormsModule to set up reactive forms in your application module.
  • Reactive forms support built-in validators and allow you to create custom validators as needed.
  • Use FormGroup and FormArray to manage complex forms with multiple controls.
  • Reactive forms provide better scalability and reusability for handling form inputs and validations.

Conclusion

Reactive forms in Angular offer a powerful and flexible way to handle form inputs and validations. By understanding and using reactive forms effectively, you can create robust and dynamic forms in your Angular applications. Happy coding!