【问题标题】:Asynchronous validation problem in angular form角度形式的异步验证问题
【发布时间】:2021-03-22 22:01:04
【问题描述】:

我想分两步验证一个名为“name”的字段,首先是同步的,然后是异步检查是否仅在表单提交之后才使用“name”。

app.component.html

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <input type="text" formControlName="name"/>
  <div *ngIf="name?.invalid && (name?.dirty || name?.touched)">
    <div *ngIf="name?.errors?.maxlength">
      Max error
    </div>
  </div>
  <div *ngIf="myForm?.errors?.hasTaken">
    This name is already taken
  </div>
  <button type="submit">Go</button>
</form>

app.component.ts

import { Component, Injectable } from '@angular/core';
import {AbstractControl, AsyncValidator, FormControl, FormGroup, ValidationErrors, Validators} from '@angular/forms';
import {combineLatest, from, Observable, of} from 'rxjs';
import {map} from 'rxjs/operators';


// simulation of validation
function UniqueNameValidator(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
  let promise = new Promise<ValidationErrors | null>((resolve, reject) => {
    const nameControl = control.get('name');
    if (nameControl?.value === 'ok') {
      setTimeout(() => resolve(null), 1000)
    } else {
      setTimeout(() => resolve({
        hasTaken: true
      }), 1000)
    }
  })
  return promise;
}


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  myForm = new FormGroup({
    name: new FormControl('', {
      validators: Validators.maxLength(10),
    })
  }, {
    asyncValidators: UniqueNameValidator,
    updateOn: 'submit'
  });

  onSubmit() {
    console.log(this.myForm)
  }

  get name() { return this.myForm.get('name'); }
}

但我得到的是对异步验证的调用,即使我在输入中没有输入任何内容并且不按下按钮。

如何解决此问题并同步验证,然后在提交后使用异步验证?

【问题讨论】:

    标签: angular typescript


    【解决方案1】:

    在调用你的承诺之前检查输入字符串的长度

    function UniqueNameValidator(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
      if(nameControl?.value.length < 10){
        return Promise.resolve()
      }
      let promise = new Promise<ValidationErrors | null>((resolve, reject) => {
        const nameControl = control.get('name');
        if (nameControl?.value === 'ok') {
          setTimeout(() => resolve(null), 1000)
        } else {
          setTimeout(() => resolve({
            hasTaken: true
          }), 1000)
        }
      })
      return promise;
    }
    

    看起来您是在表单而不是输入上调用验证器。我更喜欢[form builder][1],但是...

    // with FB injected as fb
    const form = this.fb.group({name:[null, [Validators.max(10)], [UniqueNameValidator] ]})
    

    作为奖励,您可以将最小长度值传递给验证器。您可以通过将 UniqueNameValidator 包装在一个函数中来做到这一点。您可以在哪里称呼它,例如UniqueNameValidatorWrapper(10)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-26
      相关资源
      最近更新 更多