Angular 10|9 Reactive Form Validation Messages for Email, Password, Name and Address

In this Angular tutorial, we’ll create a form using the Reactive Form approach and show validation messages if the user enters an invalid value. Form Controls will be used with Bootstrap styling to show error messages.

Angular forms can be easily created by using the Template-driven or Reactive form approach. In this tutorial, we are going to build a Reactive Form using FormControl having few Input Form fields.

The styling of the form will use Bootstrap. The validation messages will be shown on each form control in the template HTML when the user enters invalid or doesn’t fill any value for required fields or tries to submit the incomplete form.

The validation messages will be shown if the user focuses on a field but doesn’t enter a value or enter the wrong value.

Let’s start building…

 

 

Using Bootstrap Style

To quickly use bootstrap style inside the application, just include the bootstrap.css file in the HEAD section of the index.html file at Angular project root.

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

 

Adding Template HTML

In the App component template, we’ll add a form with four Input control fields, Name, Email, Address and Password.

The <form> will have [formGroup]="addUserForm" and (ngSubmit) event handler.

Then add each form control field for Name, Email, Address, and Password.

<form [formGroup]="addUserForm" (ngSubmit)="submitUser()">

    <!-- Name control -->
    <div class="form-group row">
        <label class="col-sm-2 col-form-label">*Name</label>
        <div class="col-sm-10">

            <input type="text" formControlName="name" class="form-control" placeholder="Enter name">

        </div>
    </div>

    <!-- Email control -->
    <div class="form-group row">
        <label class="col-sm-2 col-form-label">*Email</label>
        <div class="col-sm-10">

            <input type="text" formControlName="email" class="form-control" placeholder="Enter email">

        </div>
    </div>

    <!-- Address control -->
    <div class="form-group row">
        <label class="col-sm-2 col-form-label">*Address</label>
        <div class="col-sm-10">

            <textarea class="form-control" formControlName="address" placeholder="Enter address" rows="3"></textarea>

        </div>
    </div>

    <!-- Password control -->
    <div class="form-group row">
        <label class="col-sm-2 col-form-label">*Password</label>
        <div class="col-sm-10">

            <input type="password" formControlName="password" class="form-control" placeholder="Enter password">

        </div>
    </div>

    <div class="form-group text-center">
        <button type="submit" class="btn btn-success btn-sm">Add User</button>
    </div>

</form>

Each control is having the formControlName to get value. We haven’t implemented the elements required to show validation messages yet.

 

Handling the Form in Class Component

In the AddUserComponent, initialize the addUserForm with FormGroup

addUserForm: FormGroup;

A variable is used as a flag to check when a form is submitted

isFormSubmitted = false;

In the ngOnInit() hook, assign FormControl for each form field

ngOnInit(){

    this.addUserForm = this.formBuilder.group({
      name: [ '' ],
      email: [''],
      address: [''],
      password: ['']
    });
    
}

Each field is having empty value on start.

Add a submitUser() method to handle form submit.

submitUser() {

    // Set flag to true
    this.isFormSubmitted = true;

    // Form field values
    console.log(this.addUserForm.value);
}

Now we have a working form, in next section, we’ll implement the validation part.

 

Update FormBuilder Group for Validation

To add validation, first, update the formBuilder‘s group method configuration. Each FormControl will have a Validation array.

ngOnInit(): void {

    // Patterns
    const PAT_NAME = "^[a-zA-Z ]{2,20}$";
    const PAT_EMAIL = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+[.][a-zA-Z]{2,4}$";

    this.addUserForm = this.formBuilder.group({
      name: ['', [Validators.required, Validators.pattern(PAT_NAME)]],
      email: ['', [Validators.required, Validators.pattern(PAT_EMAIL)]],
      address: ['', Validators.required],
      password: ['', [Validators.required, Validators.minLength(8)]]
    });

}

Above, with each control, we have an Array of Validators required. For Name & Email, we have required and pattern validation checks. The password field must be required and have a minimum of 8 characters.

 

Update Form Template

To show error messages we will add a class ‘is-invalid’ for each control only if :

The Form is submitted & field is Invalid. OR The field is not pristine (touched by user) and invalid. So there two cases when the form filed will be red to indicate the error.

After each form filed we’ll add an error block to show error messages.

<!-- User form for Add/ Edit -->
        <form [formGroup]="addUserForm" (ngSubmit)="submitUser()">

            <!-- Name control -->
            <div class="form-group row">
                <label class="col-sm-2 col-form-label"><span class="required-asterisk">*</span>Name</label>
                <div class="col-sm-10">
                    <!-- Alerts user when control is interacted or form is submitted about errors-->
                    <input type="text" formControlName="name" class="form-control" placeholder="Enter name"
                        [ngClass]="{ 'is-invalid': (isFormSubmitted && addUserForm.controls.name.errors) || (!addUserForm.controls.name.pristine && addUserForm.controls.name.invalid) }">

                    <!-- Validation messages -->
                    <div class="invalid-feedback"
                        *ngIf="(isFormSubmitted && addUserForm.controls.name.errors) || (!addUserForm.controls.name.pristine && addUserForm.controls.name.invalid)">
                        <div *ngIf="addUserForm.controls.name.errors.required">Name is required</div>
                        <div *ngIf="addUserForm.controls.name.errors.pattern">Only Alphabets with space
                            between 2 to
                            20
                            characters</div>

                    </div>
                </div>
            </div>

            <!-- Email control -->
            <div class="form-group row">
                <label class="col-sm-2 col-form-label"><span class="required-asterisk">*</span>Email</label>
                <div class="col-sm-10">

                    <input type="text" formControlName="email" class="form-control" placeholder="Enter email"
                        [ngClass]="{ 'is-invalid': (isFormSubmitted && addUserForm.controls.email.errors) || (!addUserForm.controls.email.pristine && addUserForm.controls.email.invalid) }">

                    <!-- Validation messages -->
                    <div class="invalid-feedback"
                        *ngIf="(isFormSubmitted && addUserForm.controls.email.errors) || (!addUserForm.controls.email.pristine && addUserForm.controls.email.invalid)">
                        <div *ngIf="addUserForm.controls.email.errors.required">Email is required</div>
                        <div *ngIf="addUserForm.controls.email.errors.pattern">Enter valid email</div>

                    </div>
                </div>
            </div>

            <!-- Address control -->
            <div class="form-group row">
                <label class="col-sm-2 col-form-label"><span class="required-asterisk">*</span>Address</label>
                <div class="col-sm-10">

                    <textarea class="form-control" formControlName="address" placeholder="Enter address" rows="3"
                        [ngClass]="{ 'is-invalid': (isFormSubmitted && addUserForm.controls.address.errors) || (!addUserForm.controls.address.pristine && addUserForm.controls.address.invalid) }"></textarea>

                    <!-- Validation messages -->
                    <div class="invalid-feedback"
                        *ngIf="(isFormSubmitted && addUserForm.controls.address.errors) || (!addUserForm.controls.address.pristine && addUserForm.controls.address.invalid)">
                        <div *ngIf="addUserForm.controls.address.errors.required">Address is required</div>

                    </div>
                </div>
            </div>

            <!-- Password control -->
            <div class="form-group row">
                <label class="col-sm-2 col-form-label"><span class="required-asterisk">*</span>Password</label>
                <div class="col-sm-10">

                    <input type="password" formControlName="password" class="form-control" placeholder="Enter password"
                        [ngClass]="{ 'is-invalid': (isFormSubmitted && addUserForm.controls.password.errors) || (!addUserForm.controls.password.pristine && addUserForm.controls.password.invalid) }">

                    <!-- Validation messages -->
                    <div class="invalid-feedback"
                        *ngIf="(isFormSubmitted && addUserForm.controls.password.errors) || (!addUserForm.controls.password.pristine && addUserForm.controls.password.invalid)">
                        <div *ngIf="addUserForm.controls.password.errors.required">Password is required</div>
                        <div *ngIf="addUserForm.controls.password.errors.minlength">Minimum 8 characters required</div>
                    </div>
                </div>
            </div>

            <div class="form-group text-center">
                <!-- Dynamic text of submit button -->
                <button type="submit" class="btn btn-success btn-sm">{{urlParams?'Update':'Add'}} User</button>
                 
                <!-- Cancel button is shown when User is in edit mode -->
                <a type="submit" class="btn btn-danger btn-sm" (click)="closeModal('close')"
                    *ngIf="urlParams">Cancel</a>
            </div>

        </form>

We have error messages for each validation criteria.

 

That’s it for Angular Reactive form validation.

 

Final Code for Component Class

The component class will finally have the following code with the updated submitUser() method.

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-add-user',
  templateUrl: './add-user.component.html',
  styleUrls: ['./add-user.component.scss']
})
export class AddUserComponent implements OnInit {

  // Initializing User Form
  addUserForm: FormGroup;

  // Flag to check if form submitted by user to handle error messages
  isFormSubmitted = false;


  constructor(
    private formBuilder: FormBuilder
  ) { }

  ngOnInit(): void {

    // Patterns
    const PAT_NAME = "^[a-zA-Z ]{2,20}$";
    const PAT_EMAIL = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+[.][a-zA-Z]{2,4}$";

    // Defining Form Controlls with initial value and validations for each form controll
    this.addUserForm = this.formBuilder.group({
      name: ['', [Validators.required, Validators.pattern(PAT_NAME)]],
      email: ['', [Validators.required, Validators.pattern(PAT_EMAIL)]],
      address: ['', Validators.required],
      password: ['', [Validators.required, Validators.minLength(8)]]
    });
  }

  // Submit User Form
  submitUser() {

    // Set flag to true
    this.isFormSubmitted = true;

    // Return if form is invalid
    if (this.addUserForm.invalid) {
      return;
    }
    console.log('Submit', this.addUserForm.value);
  }

}

 

Now the form will look like this when you run the Angular application by hitting $ ng serve --open.

Conclusion

We discussed how to easily create an Angular Reactive approach based form with Validations using Required and Patters conditions and showing error messages to users using Bootstrap styling.

 

Leave a Comment

Your email address will not be published. Required fields are marked *