web-dev-qa-db-fra.com

Angular - assigner un validateur personnalisé à un FormGroup

J'ai besoin d'assigner un validateur personnalisé à un FormGroup. Je peux le faire au moment où le FormGroup est créé comme ceci:

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;
      }
}

J'ai cependant une situation où j'ai besoin d'ajouter le validateur personnalisé après j'ai instancié le FormGroup, donc j'essaie de le faire après instancier myForm, au lieu d'ajouter le validateur lorsque le formulaire est instancié:

let myForm : FormGroup;

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

this.myForm.validator = this.comparisonValidator;

Cela me donne une erreur de compilation:

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

Comment attribuer un validateur à mon FormGroup pour que le formGroup soit passé comme argument à ma fonction comparisonValidator?

pdate - J'ai ajouté une ligne indiquant où je fais un setErrors dans mon comparisonValidator, pour que ce soit plus clair exactement comment j'essaye de définir un erreur de validation.

9
Chris Halcrow

J'ai créé un stackblitz jetez un oeil.

Dans le fichier component.ts

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;
    };
 }
}

Dans le fichier component.html

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

Pour définir les validateurs (prédéfinis ou douaniers) après l'instanciation du formGroup, vous devrez utiliser la méthode setValiators () de FormGroup. Pour Ex:

  let myFormGroup = this.    _fb.group({
      control1: new FormControl('1', [])
    });
  myFormGroup.setValidators(this.customValidators());
  customValidators(): ValidatorFn {
   let myFun = (cc: FormGroup): ValidationErrors => {
     if(cc.valid) return null;
     else return {something: 'someError'};
   };
   return myFun;
  }

Vous pouvez jouer ici.

3
Shadab Faiz

Merci à @Anuradha Gunasekara - sa réponse est la solution la plus correcte et la plus complète. Une "solution rapide" pour mon erreur consistait simplement à ajouter un type de retour de any sur le validateur. Je peux toujours affecter le validateur personnalisé au FormGroup, et le FormGroup sera passé implicitement comme argument à mon validateur personnalisé. Ce code fonctionnera:

let myForm : FormGroup;

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

this.myForm.validator = this.comparisonValidator;

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