Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why should I use Validators.compose()?

I have a field I want to validate with multiple validators.
Using the Module Driven approach the code looks likes this:

this.exampleForm = this.fb.group({   date_start : [     '',     Validators.compose([       Validators.required,       Validators.pattern("[0-9]{2}-[0-9]{2}-[0-9]{4}")     ])] }) 

But I can also write this withouth Validators.compose() like:

this.exampleForm = this.fb.group({   date_start : [     '',     [       Validators.required,       Validators.pattern("[0-9]{2}-[0-9]{2}-[0-9]{4}")     ]   ] }) 

And it works just fine. Personally I prefer the 2nd version (without compose), less code and better readability. And this begs the question, why should I use Validators.compose()?

like image 298
Mihailo Avatar asked Feb 22 '17 14:02

Mihailo


People also ask

What are validators in angular?

A validator is a function that processes a FormControl or collection of controls and returns an error map or null. A null map means that validation has passed.

Is it possible to define validators in form builder?

FormBuilder allows us to explicitly declare forms in our components. This allows us to also explicitly list each form control's validators. In our example we are going to build a small form with three inputs, user name, email and profile description. We will start with looking at our app.

What is the concept of validation checks in angular forms?

Angular uses directives to match these attributes with validator functions in the framework. Every time the value of a form control changes, Angular runs validation and generates either a list of validation errors that results in an INVALID status, or null, which results in a VALID status.

How will you add validators in FormControl?

We can add Validators dynamically using the SetValidators or SetAsyncValidators. This method is available to FormControl, FormGroup & FormArray. There are many use cases where it is required to add/remove validators dynamically to a FormControl or FormGroup.


Video Answer


2 Answers

When we create new FormControl/FormGroup/FormArray(AbstractControl) - coerceToValidator is called.

function coerceToValidator(     validatorOrOpts?: ValidatorFn | ValidatorFn[] | AbstractControlOptions | null): ValidatorFn|     null {   const validator =       (isOptionsObj(validatorOrOpts) ? (validatorOrOpts as AbstractControlOptions).validators :                                        validatorOrOpts) as ValidatorFn |       ValidatorFn[] | null;    return Array.isArray(validator) ? composeValidators(validator) : validator || null; }  export function composeValidators(validators: Array<Validator|Function>): ValidatorFn|null {   return validators != null ? Validators.compose(validators.map(normalizeValidator)) : null; } 

So there is no need to compose validators before we pass it to an AbstractControl.

6/13/16 was added feat(forms): compose validator fns automatically if arrays from now on, Validators.compose is there for backward compatibility.

like image 111
Buggy Avatar answered Sep 17 '22 22:09

Buggy


I know this is an old-ish question, but it came up on a recent search.

The main reason you may want to use Validators.compose() is to reuse multiple validators. Let's say you want to check that a value is between 0 and 100. The first time, you would write:

this.form = this.fb.group({   foo: [ 0, [ Validators.min(0), Validators.max(100)]] }); 

Now let's say you want to do that in several places within your app. To avoid code duplication, you would create your own validator by simply composing it from the existing validators, expose it and reuse it everywhere you need:

// custom-validators.ts import { Validators } from '@angular/forms'; export class CustomValidators {   readonly betweenZeroHundred = Validators.compose([     Validators.min(0),     Validators.max(100),   ]); }  // form1  this.form = this.fb.group({   foo: [ 0, [CustomValidators.betweenZeroHundred()]] });  // form2 this.form = this.fb.group({   bar: [ 100, [CustomValidators.betweenZeroHundred()]] });  

Nowadays, with the spread operator, you can achieve a similar result, without the compose():

export class CustomValidators {   readonly betweenZeroHundred = [Validators.min(0), Validators.max(100)]; }  this.form = this.fb.group({   bar: [ 100, [...CustomValidators.betweenZeroHundred, Validators.required]] });   

In the end, it's a matter of which approach is a better fit for your team and your situation.

like image 22
Eric Liprandi Avatar answered Sep 17 '22 22:09

Eric Liprandi