DEV Community

Ushmi Dave
Ushmi Dave

Posted on

Improve your way to validate angular reactive forms

When it to comes to large data oriented forms, complexity increases while validating the controls and so it becomes necessary to use a better and efficient approach to validate them.

One of the most efficient approach is decorator based validation, the benefit of using it is you can use model based strategy to construct angular reactive forms in which you just need to add a decorator @alpha(),@required() on the class property, you don't need to add any extra code in HTML or create any custom validation function in the component

Let's make it happen in a few steps:

1) Install @rxweb/reactive-form-validators

npm install @rxweb/reactive-form-validators

2) You also need import RxReactiveFormsModule in the app.module.

  import { NgModule } from '@angular/core';
  import { BrowserModule } from '@angular/platform-browser';
  import { FormsModule,ReactiveFormsModule } from '@angular/forms';

  import { AppComponent } from './app.component';

  import {  RxReactiveFormsModule } from "@rxweb/reactive-form-validators"
  @NgModule({
  imports:      [ BrowserModule, 
  FormsModule,ReactiveFormsModule,RxReactiveFormsModule ],
  declarations: [AppComponent],
  bootstrap:    [ AppComponent]
  })
  export class AppModule { }
Enter fullscreen mode Exit fullscreen mode

3) Create User Model:
Let's create a user model class and create properties like firstName, lastName and username, password and confirmPassword into it and pass the respective validation decorators.

import { required, compare, alpha, minLength } from "@rxweb/reactive-form-validators";

export class User {

@required()
firstName:string;

@required()
lastName:string;

@required()
@alpha()
userName:string;

@required()
@minLength({value:8})
password:string;

@required()
@compare({fieldName:'password'})
confirmPassword:string;

}
Enter fullscreen mode Exit fullscreen mode

4) Create user component:
Now, Let's create a user component for building the reactive form based upon our model class. for that you need to import RxFormBuilder and create the formGroup object with the use of the user model class.

import { Component, OnInit } from '@angular/core';
import { FormGroup } from "@angular/forms"
import { RxFormBuilder } from '@rxweb/reactive-form-validators';
import { User } from './user.model';
@Component({
selector: 'app-user',
templateUrl: './user.component.html'
})
export class UserComponent implements OnInit {
userFormGroup: FormGroup 
constructor(
private formBuilder: RxFormBuilder 
) { }
  ngOnInit() 
  {
  let user = new User();
  this.userFormGroup = this.formBuilder.formGroup(user); 
}
} 
Enter fullscreen mode Exit fullscreen mode

5) Create user form:
Create a user form and inside the formGroup element define all the properties as formControl

<h1 class="bd-title" id="content">User Registration Form</h1>
<br/>
<form *ngIf="userFormGroup" [formGroup]="userFormGroup">
<div class="form-group">
<label>First Name</label>
<input type="text" formControlName="firstName" class="form-control" />
<small class="form-text text-danger" *ngIf="userFormGroup.controls.firstName.errors">{{userFormGroup.controls.firstName.errors.required.message}}<br/></small>
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" formControlName="lastName" class="form-control" />
<small class="form-text text-danger" *ngIf="userFormGroup.controls.lastName.errors">{{userFormGroup.controls.lastName.errors.required.message}}<br/></small>
</div>
<div class="form-group">
<label>User Name</label>
<input type="text" formControlName="userName" class="form-control" />
<small class="form-text text-danger" *ngIf="userFormGroup.controls.userName.errors && userFormGroup.controls.userName.errors.required">{{userRegistrationFormGroup.controls.userName.errors.required.message}}<br/></small>
<small class="form-text text-danger" *ngIf="userFormGroup.controls.userName.errors && userFormGroup.controls.userName.errors.alpha">{{userFormGroup.controls.userName.errors.alpha.message}}<br/></small>
</div>
<div class="form-group">
<label>Password</label>
<input type="password" formControlName="password" class="form-control" />
<small class="form-text text-danger" *ngIf="userFormGroup.controls.password.errors && userFormGroup.controls.password.errors.required">{{userFormGroup.controls.password.errors.required.message}}</small>
<small class="form-text text-danger" *ngIf="userFormGroup.controls.password.errors && userFormGroup.controls.password.errors.minLength">{{userFormGroup.controls.password.errors.minLength.message}}<br/></small>
</div>
<div class="form-group">
<label>Confirm Password</label>
<input type="password" formControlName="confirmPassword" class="form-control" />
<small class="form-text text-danger" *ngIf="userFormGroup.controls.confirmPassword.errors && userFormGroup.controls.confirmPassword.errors.compare">{{userFormGroup.controls.confirmPassword.errors.compare.message}}<br/></small>
</div>
<button [disabled]="!userFormGroup.valid" class="btn btn-primary">Submit</button>
</form>
Enter fullscreen mode Exit fullscreen mode

6) Configure validation messages globally

For displaying the validation messages if the formControl becomes invalid. you need to configure it globally in app component

You have to use ReactiveFormConfig class set method and pass the validation message object.

ReactiveFormConfig.set({
  "validationMessage": {
     "required": "This field is required.",
     "minLenght":"Enter minimum length of {{0}} characters.",
     "compare":"The value should be matched with {{0}}.",
     "alpha":"you can only enter alphabets."
}
});
Enter fullscreen mode Exit fullscreen mode

Please refer the working example code

Other benefits to use this approach:

Conditional validation :

In some of the cases you may require your validation to be fired based upon some condition. To implement it using decorator based approach you must pass parameter conditionalExpression in the decorator above the property.

import {required} from "@rxweb/reactive-form-validators"

export class User{

  @required()  
  firstName:string;

  @required({conditionalExpressions:(x=>x.firstName == "John")})
  lastName:string;

}  
Enter fullscreen mode Exit fullscreen mode

Please refer the working example

Show Custom Message :

If you want to show a custom validation message on a particular field, You must pass it in message parameter in the decorator above the property.

import {required} from "@rxweb/reactive-form-validators"

export class User{

  @required()  
  firstName:string;

  @required({message:"Last Name is required"})
  lastName:string;

}
Enter fullscreen mode Exit fullscreen mode

Please refer the working example

This validation framework has several other validators which can be used directly in component without creating custom validation functions

If you have any question/suggestion, Please share your comments below.

Top comments (0)