Вы хотите динамически установить требуемый контроль реактивных форм. Для этого я бы создал собственный валидатор, а не пытался управлять списком валидаторов, прикрепленных к элементу управления.
Во-первых, чтобы упростить ссылки на элементы управления, я собираюсь объявить их отдельно.
controls: {
phoneNumber: FormControl;
type: FormControl;
};
form: FormGroup;
types = [
'Mobile',
'Home',
'Work'
];
Я собираюсь объявить мой собственный ValidatorFn
, в который введен другой элемент управления. Валидатор будет возвращать ошибки валидации только в том случае, если введенный элемент управления имеет значение, а текущий элемент управления - нет.
private requiredIf(target: AbstractControl, other: AbstractControl): ValidatorFn {
other.valueChanges.subscribe(value => {
target.updateValueAndValidity();
});
return (control: AbstractControl) => {
return !other.value || control.value ? null : {
required: 'true'
};
};
}
Затем я установлю элементы управления в ngOnInit()
. Я должен установить валидаторы после того, как элементы управления были созданы, чтобы я мог использовать ссылку.
ngOnInit() {
this.controls = {
phoneNumber: new FormControl(''),
type: new FormControl('')
};
this.controls.phoneNumber.setValidators([
this.requiredIf(this.controls.phoneNumber, this.controls.type),
Validators.pattern('\\d+')
]);
this.form = this.formBuilder.group(this.controls);
}
HTML почти тривиален. Я проверяю объект ошибок на экземплярах FormControl
, которые я объявил вне группы форм.
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div>
<label>Type</label>
</div>
<div>
<select formControlName="type">
<option value="">Select</option>
<option *ngFor="let type of types" [ngValue]="type">
{{type}}
</option>
</select>
</div>
<div>
<label>Phone number</label>
</div>
<div>
<input formControlName="phoneNumber" />
</div>
<div *ngIf="controls.phoneNumber.errors?.required">
Required
</div>
<div *ngIf="controls.phoneNumber.errors?.pattern">
Invalid pattern
</div>
<div>
<button>Submit</button>
</div>
</form>
DEMO: https://stackblitz.com/edit/angular-fz6jjq