反应性Angular表单等待异步验证器在提交时完成 [英] Reactive Angular form to wait for async validator complete on submit

查看:530
本文介绍了反应性Angular表单等待异步验证器在提交时完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在建立反应性的角度形式,我试图找到一种方法来触发所有提交的验证器.如果验证者是同步者,那没关系,因为我可以内联它的状态.否则,如果验证器是一个异步验证器,并且尚未被触发,则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发出表单提交,您可以switchMapform.statusChangefilter结果.

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)确保在未决之后的第一个发射流已完成:VALIDINVALID.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆