State and Error Management in Angular Forms

Master how to track form states and provide clear, dynamic error feedback in Angular for a perfect user experience.

📝

Welcome! Let's see how Angular helps manage form states and errors in real-time.

/* Starting the form journey... */

Tracking Control States

Angular tracks the state of each form control. Key properties like valid, invalid, touched (visited), untouched, dirty (changed), and pristine (unchanged) tell you exactly what the user has done, allowing you to build a responsive UI.

Handling Validation Errors

When a validator fails, Angular adds a key to the control's errors object. For example, a failed required validator adds { required: true }. You can check for these keys to display specific error messages.

Providing User Feedback

The best practice is to show error messages only after the user has interacted with a field (i.e., it's touched). Combining state checks like *ngIf="control.invalid && control.touched" prevents showing errors prematurely and improves the user experience.

Building a Dynamic UI

By binding to these properties in your template, you can dynamically add CSS classes (e.g., for red borders), show or hide error messages, and disable buttons until the form is valid. This creates a seamless and intuitive experience for the user.

Practice Zone


Interactive Test 1: Categorize Concepts

Drag the items to their correct category: State Property or Error Key.

Arrastra en el orden correspondiente.


Arrastra las opciones:

touched
required
dirty
minlength

Completa el código:

Form State Properties______
Validation Error Keys______
Unlock with Premium

Interactive Test 2: Complete the Template

Rellena los huecos en cada casilla.


<div *ngIf="name. && (name. || name.)">
  <div *ngIf="name.errors?.">
    Name is required.
  </div>
</div>
Unlock with Premium

Practice Example: Code Editor

Implement a form with a name field that is required. Show an error message only when the field is invalid and has been touched.

* Write the code below. Correct characters will be shown in green and incorrect ones in red.

import { Component } from '@angular/core'; import { FormGroup, FormControl, Validators } from '@angular/forms'; @Component({ selector: 'app-form-state', template: ` <form [formGroup]="userForm" (ngSubmit)="onSubmit()"> <label for="username">Username:</label> <input type="text" id="username" formControlName="username" /> <div *ngIf="userForm.get('username')?.invalid && userForm.get('username')?.touched"> Username is required. </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> <label for="age">Age:</label> <input type="number" id="age" formControlName="age" /> <div *ngIf="userForm.get('age')?.invalid && userForm.get('age')?.touched"> You must be at least 18 years old. </div> <button type="submit" [disabled]="userForm.invalid">Submit</button> </form> <p *ngIf="formSubmitted">Form submitted successfully </p> ` }) export class FormStateComponent { formSubmitted = false; userForm = new FormGroup({ username: new FormControl('', Validators.required), email: new FormControl('', [Validators.required, Validators.email]), age: new FormControl('', [Validators.required, Validators.min(18)]) }); onSubmit() { if (this.userForm.valid) { this.formSubmitted = true; console.log('Form submitted:', this.userForm.value); } } }
Unlock with Premium

Knowledge Check

Which property tells you if a user has visited a form field?


Unlock with Premium

Advanced Error Handling Strategies

Good error handling goes beyond showing a single message. Angular's reactive forms allow for sophisticated, user-friendly feedback systems.


1. Showing Different Messages for Different Errors

A field can have multiple validators (e.g., `required` and `minlength`). You can use `*ngIf` to check for each specific error on the `errors` object and show the most relevant message.

<div *ngIf="name.errors?.required">Required</div>
<div *ngIf="name.errors?.minlength">Too short</div>

Too short

2. Creating a Reusable Error Component

To avoid repetition, you can create a component that takes a form control as an input and automatically displays the correct error message. This keeps your form templates clean and maintainable.

<!-- In your form template -->
<app-error-display [control]="name"></app-error-display>

<!-- app-error-display.component.ts -->
@Input() control: FormControl;
[Error Component]

Practical Takeaway: Combine state properties (`touched`, `dirty`) with error checks (`errors` object) to build robust, user-friendly forms that guide users toward successful submission.

Form State Glossary

control.valid / control.invalid
A boolean that is `true` if the control's value has passed all its validation rules.
control.touched / control.untouched
A boolean that becomes `true` as soon as the user has triggered a `blur` event on the element.
control.dirty / control.pristine
A boolean that becomes `true` as soon as the user has changed the value in the UI. `pristine` means the value has not been changed.
control.errors
An object containing any validation errors. If there are no errors, it is `null`. Each failed validator adds a key-value pair to this object.
control.status
A string indicating the control's validation status: 'VALID', 'INVALID', 'PENDING', or 'DISABLED'.