如何触发 Angular2中的表单验证器

在 angular2中,当另一个控件被更改时,我想触发某些控件的验证器。有没有什么方法可以让我告诉表单重新验证?更好的是,我可以请求对特定字段进行验证吗?

例如: 给定复选框 X 和输入 P。 输入 P 有一个验证器,它的行为与 X 的模型值不同。 当选中/未选中 X 时,我需要调用 P 上的验证器。P 上的验证器将查看模型以确定 X 的状态,并相应地验证 P。

这里有一些代码:

constructor(builder: FormBuilder) {
this.formData = { num: '', checkbox: false };


this.formGp = builder.group({
numberFld: [this.formData.num, myValidators.numericRange],
checkboxFld: [this.formData.checkbox],
});
}


this.formGp.controls['checkboxFld'].valueChanges.observer({
next: (value) => {
// I want to be able to do something like the following line:
this.formGp.controls['numberFld'].validator(this.formGp.controls['numberFld']);
}
});

有人有办法吗? 谢谢!

102249 次浏览

I don't know if you are still looking for an answer, so here is my suggestions:

Have a look at this: Angular 2 - AbstractControl

I think what you could do is following:

this.formGp.controls['checkboxFld'].valueChanges.observer({
next: (value) => {
this.formGp.controls['numberFld'].updateValueAndValidity();
}
});

This should trigger and run the validators. Furthermore the state gets updated as well. Now you should be able to consult the checkbox value within your validator logic.

Hope this helps!

Validaton-Guide

FormControl Documentation

with my ControlGroup I do this because I have errors divs checking if touched

for (var i in this.form.controls) {
this.form.controls[i].markAsTouched();
}

(this.form is my ControlGroup)

There are more elegant ways of modeling this behavior - for example, putting your state into a ReplaySubject and observing that, and then using async validators observing the state - but the pseudo-coded approach below should work. You simply observe the value changes in the checkbox, update the model as appropriate, then force a re-validation of the numberFld with the updateValueAndValidity cal.

constructor(builder: FormBuilder) {
this.formData = { num: '', checkbox: false };
const numberFld = builder.control(this.formData.num, myValidators.numericRange);


const checkbox = builder.control(this.formData.checkbox);
checkbox.valueChanges.map(mapToBoolean).subscribe((bool) => {
this.formData.checked = bool;
numberFld.updateValueAndValidity(); //triggers numberFld validation
});


this.formGp = builder.group({
numberFld: numberFld,
checkboxFld: checkbox
});
}
static minMaxRange(min: number, max: number): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
if (Validators.min(min)(control)) { // if min not valid
return Validators.min(min)(control);
} else {
return Validators.max(max)(control);
}
};
}

With the help of this blog

blog link

I have came across a solution with the combine of Nightking answer

Object.keys(this.orderForm.controls).forEach(field => {
const control = this.orderForm.get(field);
control.updateValueAndValidity();


});

this.orderForm is the form group

This did the trick for me

this.myForm.markAllAsTouched();

You can trigger validation in this way:

this.myform.get('myfield').updateValueAndValidity();

Here is another similar way that also uses markAsDirty and updateValueAndValidity, particularly good if you use angular material where markAsTouched is not enough.

export function forceValidation(form: AbstractControl) {
if (form instanceof FormGroup || form instanceof FormArray) {
for (const inner in form.controls) {
const control = form.get(inner);
control && forceValidation(control);
}
} else {
form.markAsDirty();
form.markAsTouched();
form.updateValueAndValidity();
}
}