我正在 Build 一个反应式角形,我可以,因为我可以获得内联的状态 . 否则,如果验证器是异步的并且尚未触发,则 ngSubmit
方法上的表单将处于挂起状态 . 我已经尝试注册表单 statusChange
属性的订阅,但是当我使用 markAsTouched
函数调用验证时它不会被触发 .
这是一些片段:
//initialization of form and watching for statusChanges
ngOnInit() {
this.ctrlForm = new FormGroup({
'nome': new FormControl('', Validators.required),
'razao_social': new FormControl('', [], CustomValidators.uniqueName),
'cnpj': new FormControl('', CustomValidators.cnpj),
});
this.ctrlForm.statusChanges.subscribe(
x => console.log('Observer got a next value: ' + x),
err => console.error('Observer got an error: ' + err),
() => console.log('Observer got a complete notification')
)
}
//called on ngSubmit
register(ctrlForm: NgForm) {
Forms.validateAllFormFields(this.ctrlForm);
console.log(ctrlForm.pending);
//above will be true if the async validator
//CustomValidators.uniqueName was not called during form fill.
}
//iterates on controls and call markAsTouched for validation,
//which doesn't fire statusChanges
validateAllFormFields(formGroup: FormGroup) {
Object.keys(formGroup.controls).forEach(field => {
const control = formGroup.get(field);
if (control instanceof FormControl) {
control.markAsTouched({ onlySelf: true });
} else if (control instanceof FormGroup) {
this.validateAllFormFields(control);
}
});
}
关于如何确保执行异步验证器的任何想法,以便我可以继续使用触发并完成所有验证器的寄存器逻辑?
2 回答
据我所知,Angular不会在触发
ngSubmit
之前等待异步验证器完成 . 由于验证器尚未解决,因此表单可能无效 .使用
Subject
作为表单提交的事件流,您可以switchMap
到form.statusChange
和filter
结果 .从
startWith
开始确保没有悬挂发射,如果表格在提交时有效 .按
'PENDING'
过滤等待此状态更改,take(1)
确保在挂起后的第一次发射中完成流:VALID
或INVALID
.您还可以添加
tap
,触发将窗体设置为脏的副作用 .markAsTouched
将不会激活验证,而是使用markAsDirty
,然后您的自定义验证器将触发 . 所以改变......至
此外,如果您使用的是v 5,则可以使用可选的
updateOn: 'submit'
,在提交表单之前不会更新值(因此不会更新) . 为此,请进行以下更改:有了它,这意味着您不再需要调用
this.validateAllFormFields(control)
,我假设切换一些布尔标志并检查验证或类似的东西 .以下是表单的示例,在提交表单后始终返回错误:
https://stackblitz.com/edit/angular-rjnfbv?file=app/app.component.ts