web-dev-qa-db-fra.com

Angular - Ajouter/supprimer dynamiquement des validateurs

J'ai une FormGroup définie comme ci-dessous:

this.businessFormGroup: this.fb.group({
    'businessType': ['', Validators.required],
    'description': ['', Validators.compose([Validators.required, Validators.maxLength(200)])],
    'income': ['']
  })

Maintenant, lorsque businessType est Other, je souhaite supprimer Validators.required validator de description. Et si businessType n'est pas Other, je veux rajouter le Validators.required.

J'utilise le code ci-dessous pour ajouter/supprimer dynamiquement le Validators.required. Cependant, il efface le validateur Validators.maxLength existant.

if(this.businessFormGroup.get('businessType').value !== 'Other'){
    this.businessFormGroup.get('description').validator = <any>Validators.compose([Validators.required]);               
} else {                
    this.businessFormGroup.get('description').clearValidators();               
}

this.businessFormGroup.get('description').updateValueAndValidity(); 

Ma question est la suivante: comment puis-je conserver les validateurs existants lors de l'ajout/la suppression du validateur required

6
A J Qarshi

Les formes angulaires ont une fonction intégrée setValidators () qui permet l’affectation programmatique des validateurs.

Pour votre exemple, vous pouvez faire:

if(this.businessFormGroup.get('businessType').value !== 'Other'){
    this.businessFormGroup.controls['description'].setValidators([Validators.required, Validators.maxLength(200)]);              
} else {                
    this.businessFormGroup.controls['description'].setValidators([Validators.maxLength(200)]);               
}

Il est important de garder à l'esprit que en utilisant cette méthode, vous écraserez vos validateurs existants. Vous devrez donc inclure tous les validateurs dont vous avez besoin/que vous souhaitez pour le contrôle que vous réinitialisez.

12
Narm

L’approche naïve consisterait à définir les validateurs du contrôle chaque fois que la variable conditionnelle sera modifiée. Mais nous pouvons réellement faire mieux que cela en utilisant une programmation indirection + fonctionnelle.

Considérez l'existence d'un descriptionIsRequired getter, qui agit comme un drapeau boolan.

Idées:

  • Créez une fonction de validation personnalisée qui prend l'argument descriptionIsRequired et, en fonction de celui-ci, valide un contrôle par rapport à + + maxLength ou à maxLength.
  • Liez le validateur personnalisé au contrôle de description de telle sorte que, lorsque la validité du contrôle est évaluée, la dernière valeur de descriptionIsRequired soit considérée.

Le premier point est assez simple à mettre en œuvre:

function descriptionValidator(required: boolean): ValidatorFn {
  return (formControl: FormControl): ValidationErrors => {
    if (required) {
      return Validators.compose([Validators.required, Validators.maxLength(200)])(formControl);
    } else {
      return Validators.maxLength(200)(formControl);
    }
  }
}

Notez qu'il s'agit d'une fonction auto-encapsulée.

Le deuxième point est un peu plus compliqué, mais à la fin, il ressemble à ceci:

export class FooComponent {
  constructor(){
    this.form = fb.group({
      description: ['initial name', this.validator()]
    });
  }

  private get descriptionIsRequired(): boolean {
   ...
  }

  private validator(): ValidatorFn {
    return (c: FormControl): ValidationErrors => descriptionValidator(this.descriptionIsRequired)(c);
  }
}

Une petite explication de ce qui se passe:

  • la méthode validator renvoie une fonction
  • la fonction renvoyée par validator peut être considérée comme une méthode factory: chaque fois qu'elle est invoquée, renvoie une nouvelle fonction, plus précisément une nouvelle instance de notre descriptionValidator en utilisant la dernière valeur descriptionIsRequired.

Une démo en direct dans le stackblitz } _

2
Jota.Toledo

Peut-être que cela aide: 

Ajout de Validators.required au groupe de validateurs d'une AbstractControl existante:

if (c.validator !== null) {
        c.setValidators([c.validator, Validators.required])
  } else {
        c.setValidators([Validators.required])
  }
2
Rob