Angular - FormBuilder.group not accepting array of validators

Dharmvir Tiwari picture Dharmvir Tiwari · Mar 18, 2018 · Viewed 10.6k times · Source

I was trying to use extra parameter map provided by Angular FormBuilder

group(controlsConfig: {
    [key: string]: any;
}, extra: {
    [key: string]: any;
} | null = null): FormGroup

Docs : FormBuilder

But facing

this.validator is not a function

If i pass a single validator instead of an array, the above error vanishes but the validation does not happen?

Can someone help me with this or provide the correct way of using the extra map parameter?

My component and its corresponding template is as follows:

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  formGroupNew: FormGroup;
  constructor(private fb: FormBuilder) {
    this.createForm();
  }
  createForm() {
    this.formGroupNew = this.fb.group(
      { name:  "Provide name"}, 
     { validator: [Validators.required, Validators.maxLength(5)] } );
  }

  validate() {
    console.log(this.formGroupNew.controls["name"].status);
  }
}

app.component.html:

<div class="container" [formGroup]="formGroupNew">
  <input class="form-control" formControlName="name">
  <button (click)="validate()">Validate</button>
</div>

Answer

Jota.Toledo picture Jota.Toledo · Mar 20, 2018

When you do fb.group({...}, {validator: fn}), the first argument are the controls of the group and the second are configuration parameters for the group object itself, not the controls contained in it.

The error is caused because the method expects to receive a function instead of an array according to the src.

The ValidatorFn that you can pass there will be applied to the FormGroup object, so you could create custom functions to check for conditions on multiple controls in the group. For that reason it kinda makes no sense to pass something like Validators.length(5), as the value of the group is an object (how would you check that condition against an object?). On the contrary, Validators.required makes sense, as the value could be null when all controls aren't set.

Let's say that you have two custom validator functions: CustomValidatorFnOne, CustomValidatorFnTwo and you want to apply them to the group plus the required. You could do something like:

fb.group({...}, {
   validator: Validators.compose(
      [
          CustomValidatorFnOne, 
          CustomValidatorFnTwo,
          Validators.required
      ]
   )
})

That way you compose all your validators into one function.