反应性Angular表单等待异步验证器在提交时完成 [英] Reactive Angular form to wait for async validator complete on submit
问题描述
我正在建立反应性的角度形式,我试图找到一种方法来触发所有提交的验证器.如果验证者是同步者,那没关系,因为我可以内联它的状态.否则,如果验证器是一个异步验证器,并且尚未被触发,则ngSubmit
方法上的表单将处于待处理状态.我已经尝试注册表单statusChange
属性的订阅,但是当我使用markAsTouched
函数手动要求验证时,不会触发该订阅.
I am building a reactive angular form and I'm trying to find a way to trigger all validators on submit. If the validor is a sync one, it'd be ok, as I can get the status of it inline. Otherwise, if the validator is an async one and it was not triggered yet, the form on ngSubmit
method would be in pending status. I've tried to register a subscribe for the form statusChange
property, but it's not triggered when I call for validation manualy with markAsTouched
function.
以下是一些摘要:
//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);
}
});
}
关于如何确保执行异步验证器的任何想法,以便我可以继续执行触发并完成所有验证器的寄存器逻辑?
Any ideas on how can I ensure that the async validator was executed so I can continue with the register logic having all validators triggered and completed?
推荐答案
Angular在触发ngSubmit
之前不等待异步验证程序完成.因此,如果验证者尚未解决,则该表格可能无效.
Angular doesn't wait for async validators to complete before firing ngSubmit
. So the form may be invalid if the validators have not resolved.
使用Subject
发出表单提交,您可以switchMap
至form.statusChange
和filter
结果.
Using a Subject
to emit form submissions, you can switchMap
to form.statusChange
and filter
the results.
以startWith
开头,以确保在提交时该表格有效的情况下不会产生任何悬空发射.
Begin with a startWith
to ensure there's no hanging emission, in the case the form is valid at the time of submission.
按PENDING
进行过滤会等待此状态更改,并且take(1)
确保在未决之后的第一个发射流已完成:VALID
或INVALID
.
Filtering by PENDING
waits for this status to change, and take(1)
makes sure the stream is completed on the first emission after pending: VALID
or INVALID
.
//
// <form (ngSubmit)="formSubmitSubject$.next()">
this.formSubmitSubject$ = new Subject();
this.formSubmitSubject$
.pipe(
tap(() => this.form.markAsDirty()),
switchMap(() =>
this.form.statusChanges.pipe(
startWith(this.form.status),
filter(status => status !== 'PENDING'),
take(1)
)
),
filter(status => status === 'VALID')
)
.subscribe(validationSuccessful => this.submitForm());
您还可以添加tap
来触发将表单设置为脏表单的副作用.
You can also add a tap
that triggers the side effect of settings the form as dirty.
这篇关于反应性Angular表单等待异步验证器在提交时完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!