Угловой - динамически добавлять/удалять валидаторы
У меня есть FormGroup
как FormGroup
ниже:
this.businessFormGroup: this.fb.group({
'businessType': ['', Validators.required],
'description': ['', Validators.compose([Validators.required, Validators.maxLength(200)])],
'income': ['']
})
Теперь, когда businessType
is Other
, я хочу удалить Validators.required
validator из description
. И если businessType
не является Other
, я хочу добавить обратно Validators.required
.
Я использую приведенный ниже код для динамического добавления/удаления Validators.required
. Однако он очищает существующий валидатор Validators.maxLength
.
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();
Мой вопрос в том, как сохранить существующие валидаторы при добавлении/удалении required
валидатора.
Ответы
Ответ 1
Angular формы имеют встроенную функцию setValidators(), которая позволяет программно назначать валидаторы.
Для вашего примера вы можете сделать:
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)]);
}
Важно помнить, что с помощью этого метода вы перезапишете существующие валидаторы, поэтому вам нужно будет включить все валидаторы, которые вам нужны/нужны для элемента управления, который вы сбрасываете.
Ответ 2
Эта работа для меня
onAddValidationClick(){
this.formGroup.controls["firstName"].setValidators(Validators.required);
this.formGroup.controls["firstName"].updateValueAndValidity();
}
onRemoveValidationClick(){
this.formGroup.controls["firstName"].clearValidators();
this.formGroup.controls["firstName"].updateValueAndValidity();
}
Ответ 3
Наивный подход состоял бы в том, чтобы установить валидаторы управления всякий раз, когда изменяется условная переменная. Но мы можем добиться большего, чем это, используя какое-то косвенное + функциональное программирование.
Рассмотрим существование descriptionIsRequired
, которое будет использоваться в качестве флагов boolan.
Идеи:
- Создайте пользовательскую функцию валидатора, которая принимает аргумент
descriptionIsRequired
как аргумент, и в зависимости от этого проверяет контроль над требуемой + maxLength или maxLength. - Привяжите настраиваемый валидатор к элементу управления описанием таким образом, чтобы при оценке действительности элемента управления учитывалось самое новое значение
descriptionIsRequired
.
Первый момент довольно прост в реализации:
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);
}
}
}
Обратите внимание, что это функция с самопроверкой.
Второй момент немного сложнее, но в конце он выглядит так:
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);
}
}
Небольшое объяснение того, что происходит:
- метод
validator
возвращает функцию - функция, возвращаемая
validator
может считаться фабричным методом: всякий раз, когда она вызывается, возвращает новую функцию, а точнее, новый экземпляр нашего descriptionValidator
используя новое значение descriptionIsRequired
.
Живая демонстрация в следующем стеке
Ответ 4
Может быть, это поможет:
Добавление Validators.required в набор валидаторов существующего AbstractControl
:
if (c.validator !== null) {
c.setValidators([c.validator, Validators.required])
} else {
c.setValidators([Validators.required])
}
Ответ 5
Любой, кто все еще ищет ответ, может сделать это следующим образом, обработав его в ngOnInit() или в любом другом месте, которое вам нравится.
const validators = formGroup.validator; /* or control.validator */
const newValidator = CustomValidator.checkUserNameValidity();
/* Add to existing validator */
if(validator) {
formGroup.setValidators([validators, newValidator])
} else {. /* if no validators added already */
formGroup.setValidators([newValidator]);
}
Выполните то же самое для asyncValidator.