Decorator based reactive forms in Angular — An efficient way to validate forms

Kaushik Samanta
JavaScript in Plain English
4 min readMay 11, 2020

--

Image is taken from burst

When working with forms in Angular, we are provided with two choices:-

  • Template-driven forms
  • Model-based reactive forms

Each one has its own use case depending upon how complex the form is.

  • Template-driven forms are useful when it’s a simple form such as login and signup, but they don’t scale as much as reactive forms. If you have very basic and simple requirements, use template-driven forms. The main disadvantage here is, unit testing is quite complicated to do without the form model inside the component.
  • Reactive forms are more robust as they’re more scalable, reusable, and testable. Most of the heavy lifting is done from the component class by putting the instances of the input fields on the template, making it easier to unit test. If you use large data-oriented forms with complex business logic, always use reactive forms.

In this article, we will discuss the reactive forms approach with decorator based validation. But before going into that first I will explain how to work without the decorator approach.

Without Decorator

1) Import ReactiveFormsModule

First, we need to import the ReactiveFormsModule in app.module.ts.

app.module.ts

2) Template: formGroup, formControlName & ngSubmit

With reactive forms, most of the work is delegated to the component class so the template file much simpler and clear.

reactive-form.component.html

3) Component class

NgSubmit — This is the event that will be triggered upon submission of the form.

FormControl — The FormControl facilitates an individual form control, tracks the value and validation status, and also represents an input in the view. The first parameter is the default value and the second is an array of validators.

FormGroup — A FormGroup aggregates the values of each child FormControl into one object, with each control name as the key. It calculates its status by reducing the status values of its children. For example, if one of the controls in a group is invalid, the entire group becomes invalid. We can also nest the FormGroup if we want to create a complex value.

FormControlName — Each form field should have a formControlName directive with a value that will be the name used in the component class.

Then, let’s create the form in the controller in ngOnInit().

reactive-form.component.ts

OnSubmit outputs to show how we can access our form’s validity and form control values.

4) Issues with the current form validation

  • The reactive module is not strongly typed.
  • We cannot map the model object value directly with validations to the reactive form while creating a FormGroup.
  • We have to manually configure the validators on every respective property.
  • Writing too much code to manage template validation with FormControl, if there is more than one validator.

Note:- For more in depth details about reactive forms visit https://angular.io/api/forms

With Decorator

We will be using the @rxweb/reactive-form-validators angular library for the decorator based validation approach.

Here are a few advantages of using this library:-

  1. Use a model-based approach to construct reactive forms by just adding decorator like@alpha(),@required() etc on the class property.
  2. No extra code needed on the template side or any form of custom validation in the component.

Implementation

1) npm install @rxweb/reactive-form-validators

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

3) Use ReactiveFormConfig in app.module.ts and use the set method to pass the validation message object.

4) Create a user model with the respective decorators:-

@required(): All the fields should be required. If you want a custom message then pass message as a parameter in the decorator.

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

@alpha() : The userName property only accepts the alphabets. If you want to allow whitespace then pass allowWhitespace as a parameter in the decorator.

@required()@alpha({ allowWhiteSpace: true })userName: string;

@minLength({ value: 8 }) : The password property must have the minimum string length of 8 characters.

@compare({ fieldName: 'password' }) : Compare property value should be the same as the password property value.

Note:- These are just a few decorators used only for demonstration purposes. For more in-depth list of available decorators visit :-https://github.com/rxweb/rxweb/tree/master/packages/reactive-form-validators/decorators

5) Create the component class and initialize the user model instance in the ngOnInit hook and then pass it to the FormGroup of RxFormBuilder.

6) Write the Template file using formGroup, formControlName & ngSubmit

Conclusion

@rxweb/reactive-form-validators is a pretty robust library for all form validation needs in angular. Not only it supports reactive forms it also supports template-based validation through directives.

Below is an example of one of the validators from the library documentation.

allOf

This validation will check whether the user has entered all of the values of the given field or not.

Reactive Form Validation

this.employeeInfoFormGroup = this.formBuilder.group({skills: [RxwebValidators.allOf({
matchValues: ["MVC", "AngularJS","AngularJS 5","C#"]
})],
});

Template Form Validation

<input id="skills" name="skills" type="checkbox" value="{{tag.name}}" [(ngModel)]="employee.skills" [allOf]='{"matchValues":"MVC","AngularJS","AngularJS","C#"}'/>

Decorator Based Validation

@allOf({matchValues: ["MVC", "AngularJS","Angular 5","C#"]}) skills: string

--

--

Polyglot Developer — Working on multiple languages and frameworks. Experience in building scalable, maintainable and reliable codebases.