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
?
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.
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:
descriptionIsRequired
et, en fonction de celui-ci, valide un contrôle par rapport à + + maxLength ou à maxLength.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:
validator
renvoie une fonctionvalidator
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 } _
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])
}