Validation

Don’t forget to import FormsModule in app.module.ts

Required

Template driven approach

Button

Enable button only if the form is valid

<button type="submit" [disabled]="!f.valid">Submit</button>

ts

@ViewChild('f') signupForm: NgForm;

Text field

This will be treated as invalid if it’s empty

<input type="text" id="username" ngModel name="username" required>

Email

<input type="email" id="email" ngModel name="email" required email #email="ngModel">
<span class="help-block" *ngIf="!email.valid && email.touched">Please enter a valid email!</span>

Classes added by Angular automatically

class="ng-valid"
class="ng-invalid"
input.ng-invalid.ng-touched{
      border: 1px solid red;
  }

Select

Set default value of a dropdown

html

<select 
    id="secret" 
    class="form-control"
    [ngModel]="defaultQuestion"
    name="secret">
        <option value="pet">Your first Pet?</option>
        <option value="teacher">Your first teacher?</option>
</select>

ts

defaultQuestion = 'teacher';

Radio

fruits = ['apple', 'peach', 'grape'];
<div class="radio" *ngFor="let fruit of fruits">
    <label>
        <input 
            type="radio" 
            name="fruit" 
            ngModel 
            [value]="fruit" 
            required> {{fruit}}
    </label>
</div>

Template Driven Form Validation

HTML

<button (click)="showUserForm = !showUserForm" class="btn btn-dark mb-3">Add User</button>
<div class="card card-body mb-3" *ngIf="showUserForm">
  <h2>Add User</h2>
  <form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)">
    <div class="form-group">
      <label>First Name</label>
      <input 
        type="text" 
        [(ngModel)]="user.firstName" 
        [ngClass]="{'is-invalid':userFirstName.errors && userFirstName.touched}"
        class="form-control" 
        name="firstName"
        #userFirstName="ngModel"
        required
        minlength="2"
      >
      <div [hidden]="!userFirstName.errors?.required" class="invalid-feedback">
        First name required
      </div>

      <div [hidden]="!userFirstName.errors?.minlength" class="invalid-feedback">
          Must be at least 2 characters
      </div>
    </div>
    <div class="form-group">
      <label>Last Name</label>
      <input 
        type="text" 
        [(ngModel)]="user.lastName" 
        [ngClass]="{'is-invalid':userLastName.errors && userLastName.touched}"
        class="form-control" 
        name="lastName"
        #userLastName="ngModel"
        required
        minlength="2"
      >
      <div [hidden]="!userLastName.errors?.required" class="invalid-feedback">
        Last name required
      </div>

      <div [hidden]="!userLastName.errors?.minlength" class="invalid-feedback">
          Must be at least 2 characters
      </div>
    </div>
    <div class="form-group">
      <label>Email</label>
      <input 
      type="email" 
      [(ngModel)]="user.email" 
      [ngClass]="{'is-invalid':userEmail.errors && userEmail.touched}"
      class="form-control" 
      name="email"
      #userEmail="ngModel"
      required
      pattern="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"
    >
    <div [hidden]="!userEmail.errors?.required" class="invalid-feedback">
      Email name required
    </div>

    <div [hidden]="!userEmail.errors?.pattern" class="invalid-feedback">
        Email is not valid
    </div>
    </div>

    <button [disabled]="!userForm.form.valid" class="btn btn-block mb-3">Add New User</button>
  </form>
</div>
<ul class="list-unstyled" *ngIf="loaded && users?.length > 0">
  <li class="card card-body mb-2" *ngFor="let user of users" [class.bg-light]="user.isActive">
    <h3>{{ user.firstName }} {{ user.lastName }}
      <small>
        <button (click)="user.hide = !user.hide" class="btn btn-dark btn-sm">
          <i [ngClass]="user.hide ? 'fa fa-plus' : 'fa fa-minus'"></i>
        </button>
      </small>
    </h3>
    <ul class="list-group" *ngIf="!user.hide">
      <li class="list-group-item">Emial: {{ user.email }}</li>
      <li class="list-group-item">Joined: {{ user.registered | date }}</li>
    </ul>
  </li>
</ul>

<h4 *ngIf="users?.length == 0">No Users Found</h4>

<h4 *ngIf="!loaded">Loading Users...</h4>

TS

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

import { User } from '../../models/User'; 

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.css']
})
export class UsersComponent implements OnInit {
  user: User = {
    firstName: '',
    lastName: '',
    email: ''
  }
  users: User[];
  showExtended: boolean = true;
  loaded: boolean = false;
  enableAdd: boolean = false;
  showUserForm: boolean = false;
  @ViewChild('userForm') form: any;

  constructor() { }

  ngOnInit() {
   
      this.users = [
        {
          firstName: 'John',
          lastName: 'Doe',
          email: 'john@gmail.com',
          isActive: true,
          registered: new Date('01/02/2018 08:30:00'),
          hide: true
        },
        {
          firstName: 'Kevin',
          lastName: 'Johnson',
          email: 'kevin@yahoo.com',
          isActive: false,
          registered: new Date('03/11/2017 06:20:00'),
          hide: true
        },
        {
          firstName: 'Karen',
          lastName: 'Williams',
          email: 'karen@gmaial.com',
          isActive: true,
          registered: new Date('11/02/2016 10:30:00'),
          hide: true
        }
      ];

      this.loaded = true;
  }

  onSubmit({value, valid}: {value: User, valid: boolean}) {
    if(!valid){
      console.log('Form is not valid');
    } else {
      value.isActive = true;
      value.registered = new Date();
      value.hide = true;

      this.users.unshift(value);

      this.form.reset();
    }
  }

  
}

Interface

export interface User {
  firstName: string,
  lastName: string,
  email: string,
  isActive?: boolean,
  registered?: any,
  hide?: boolean
}
Was this page helpful?