Search code examples
javascriptangulartypescriptangular-reactive-formsangular-validation

Angular - assign custom validator to a FormGroup


I need to assign a custom validator to a FormGroup. I can do this at the time the FormGroup is created like this:

let myForm : FormGroup;

myForm = this.formBuilder.group({
        myControl1: defaultValue,
        myControl2: defaultValue
      }, { validator: this.comparisonValidator })

comparisonValidator(g: FormGroup) {
      if (g.get('myControl1').value > g.get('myControl2'.value)) {
        g.controls['myControl1'].setErrors({ 'value2GreaterThanValue1': true });
        return;
      }
}

I have a situation though where I need to add the custom validator after I've instantiated the FormGroup, so I'm trying to do this after instantiating myForm, instead of adding the validator when the form is instantiated:

let myForm : FormGroup;

myForm = this.formBuilder.group({
        myControl1: defaultValue,
        myControl2: defaultValue
      })

this.myForm.validator = this.comparisonValidator;

This gives me a compiler error:

Type '(g: FormGroup) => void' is not assignable to type 'ValidatorFn'.
  Type 'void' is not assignable to type 'ValidationErrors'.

How do I assign a validator to my FormGroup so that the formGroup is passed as the argument to my comparisonValidator function?

Update - I've added a line showing where I'm doing a setErrors in my comparisonValidator, to make it clearer exactly how I'm trying to set a validation error.


Solution

  • I've created a stackblitz take a look.

    In the component.ts file

    import { Component } from '@angular/core';
    import {FormBuilder,FormGroup, ValidationErrors, ValidatorFn} from '@angular/forms'
    
    @Component({
      selector: 'my-app',
      templateUrl: './app.component.html',
      styleUrls: [ './app.component.css' ]
    })
    export class AppComponent  {
      myForm: FormGroup;
      defaultValue = 20;
    
    constructor(private formBuilder: FormBuilder) {
      this.myForm = this.formBuilder.group({
            myControl1: this.defaultValue,
            myControl2: this.defaultValue
          });
          debugger
          this.myForm.setValidators(this.comparisonValidator())
    }
    
     public comparisonValidator() : ValidatorFn{
           return (group: FormGroup): ValidationErrors => {
              const control1 = group.controls['myControl1'];
              const control2 = group.controls['myControl2'];
              if (control1.value !== control2.value) {
                 control2.setErrors({notEquivalent: true});
              } else {
                 control2.setErrors(null);
              }
              return;
        };
     }
    }
    

    In the component.html file

    <div>
      <form [formGroup]="myForm">
        <input formControlName="myControl1" type="number">
        <input formControlName="myControl2"  type="number">
        <br>Errors: {{myForm.get('myControl2').errors | json}}
      </form>
    </div>