Angular2 daje programiście sporo gotowych możliwości ułatwiających walidację formularzy po stronie front-endu. Może to być bardzo pomocne dla użytkownika kiedy w trakcie wypełniania formularza na bieżąco będzie informowany o błędach.
Warto przy tym wspomnieć, że nie zawsze dobrym pomysłem będzie przygotowanie restrykcyjnej walidacji dla formularza. Przykładowo projektując formularz koszyka z zamówieniem w sklepie internetowym, obsłudze sklepu łatwiej będzie poradzić sobie z usunięciem drobnych błędów wpisanych przez klienta (np. błąd w kodzie pocztowym) niż doprowadzić do sytuacji, że poirytowany klient porzuci koszyk i zrezygnuje z zakupu.

Stany formularza w Angular2:

Na stany możemy reagować pokazując lub ukrywając konkretny komunikat oraz stany z przedrostkiem ng- dodawane, są do pól input jako klasy. To nam idealnie pomaga w stylowaniu formularza np. dodanie czerwonej ramki wokół pola input, gdy zostało ono błędnie wypełnione.

valid formularz jest poprawnie wypełniony
invalid formularz nie jest poprawnie wypełniony
submitted formularz został zatwierdzony
touched pole formularza zostało dotknięte
untouched pole formularza nie zostało dotknięte
dirty w polu formularza było coś wpisane (mogło zostać później wykasowane)
pristine w polu formularza nie było nic wpisane (jest dziewicze)
Inne stany, do których mamy dostęp:
status dane pole (nie cały formularz) jest typu Invalid czy valid
disabled dane pole jest typu disabled zwraca true/false
errors wskazuje błąd, przez który pole jest invalid
value przechowuje wartość input-a wpisaną przez użytkownika

Walidacja danych w Angular2:

required dane pole jest wymagane
minLength(4) minimalna ilość wpisanych znaków
maxLength(24) maksymalna ilość wpisanych znaków
pattern dowolny wzór określony przez wyrażenie regularne RegExp
Przykład formularza z walidacją w HTML:
<form (ngSubmit)="onSubmit(newForm.value)" novalidate="true" #newForm="ngForm">
    <div *ngIf="newForm.submitted" class="submittedError">
        <span *ngIf="emailRef.errors">Invalid email</span>
        <span *ngIf="passRef.errors">Invalid password</span>
    </div>
        <div>
            <div>
                <label for="email">E-MAIL
                    <input type="email" #emailRef="ngModel" pattern="^[a-z0-9-._]+@[a-z0-9.-]+\.[a-z]{2,}$" [(ngModel)]="user.email" name="email" class="form-control" placeholder="Email" required>
                    <div *ngIf="emailRef.touched&&emailRef.errors?.required" class="bgAlert">This field is required</div>
                    <div *ngIf="emailRef.touched&&emailRef.errors?.pattern" class="bgAlert">The email is incorrect</div>
                </label>
            </div>
            <div>
                <label for="password">PASSWORD
                    <input type="password" #passRef="ngModel" required pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}" [(ngModel)]="user.password" name="password" class="form-control" placeholder="Password">
                    <div *ngIf="passRef.touched&&passRef.errors?.required" class="bgAlert">This field is required</div>
                    <div *ngIf="passRef.touched&&passRef.errors?.pattern" class="bgAlert">Password required at least 6 characters with: digit, capital letter, lower case letter</div>
                </label>
            </div>
        </div>
        <div>
            <input type="submit" class="button" value="LOGIN">
        </div>
</form>
<style>
.form-control.ng-dirty.ng-invalid {
    border: 2px solid rgba(255,0,0,0.9);
}
.form-control.ng-dirty.ng-valid {
    border: 2px solid rgba(0,255,0,0.9);
}</style>
Przykład formularza z walidacją w komponencie:

Podejście zalecane, jeżeli do formularza będą pisane testy jednostkowe. Kod HTML jest tu krótszy, ale brakuje też styli. Podane wcześniej stany będą tutaj używane podobnie tyle, że dostęp do nich w tym konkretnym przypadku będzie poprzedzony ścieżką form2.controls. Poniżej przykład dla pola password.

<form [formGroup]="form2">
    <input type="email" placeholder="Email" formControlName="email">
    <input type="text" placeholder="street" formControlName="street">
    <input type="email" placeholder="Email" formControlName="email2">
    <input type="password" placeholder="password" formControlName="password">
    {{ form2.controls.password.valid }} 
    {{ form2.controls.password.dirty }}
    {{ form2.controls.password.pristine }}
    {{ form2.controls.password.status }}
    {{ form2.controls.password.disabled }}
    {{ form2.controls.password.touched }}
    {{ form2.controls.password.errors | json }}
    {{ form2.controls.password.value }}
</form>

A teraz właściwa walidacja w komponencie. Wszystkie pola wymagane, a oprócz tego street przynajmniej 3 znaki, e-mail 2 pattern, password pattern.

import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-member',
  templateUrl: './member.component.html',
  styleUrls: ['./member.component.css']
})
export class MemberComponent implements OnInit {
  form2: any;
  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.form2 = this.fb.group({
      email: ['', Validators.required],
      street: ['', [Validators.minLength(3), Validators.required]],
      email2: ['', [Validators.pattern("'^[a-z0-9-._]+@[a-z0-9.-]+\.[a-z]{2,}$"),
                    Validators.required]],
      password: ['', [Validators.pattern('(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}'),
                    Validators.required]]
    });
  }
}