【问题标题】:Showing error after form submit in angular reactive form以角度反应形式提交表单后显示错误
【发布时间】:2019-06-27 21:35:20
【问题描述】:

我创建了一个反应形式并使用角度材料形式控制。

在提交表单时,我正在调用 API,该 API 正在返回错误,因为其中一个 formControl 值无效

例如Website already registered

现在,我想在 中显示此错误消息,但错误未显示。

  <mat-form-field class="full-width website"
    [appearance]="matAppearance">
    <mat-label>Website URL</mat-label>
    <input matInput
      placeholder="Website URL"
      name="website"
      formControlName="website">
    <mat-error *ngIf="configurationForm.get('website').hasError('required')">
      <strong>(required)</strong>
    </mat-error>
    <mat-error *ngIf="configurationForm.get('website').hasError('pattern')">
      Invalid URL
    </mat-error>
    <mat-error *ngIf="websiteErrMsg">{{websiteErrMsg}}</mat-error>
  </mat-form-field>

  public submitForm() {
      this.testService.register().subscribe(
        sucRes => {
          console.log('done);
        },
        errRes => {
          if (errRes.error === 'Website is already registered') {
              this.websiteErrMsg = 'Website Already Registered!';
          }
        }
      );
  }

问题 1:我做错了什么?

编辑: 我试过更改mat-errordiv,然后就可以了。现在想知道为什么它不适用于mat-error

【问题讨论】:

  • MatFormField 仅在 FormControl 出现错误时显示 mat-error 元素。它不会仅仅因为您通过ngIfElse 告诉它而显示。如果您在mat-form-field 之外提供mat-error,那么它可以工作..
  • 提交表单后有没有办法设置formcontrol错误。我已经尝试调用this.configurationForm.get('website').setErrors({apiErr: true}); 并在html 中进行了必要的更改&lt;mat-error *ngIf="configurationForm.get('website').hasError('apiErr') &gt;some api error happened&lt;/mat-error&gt;
  • 我认为您只需要使用自定义验证器来处理此问题..
  • 你能提供 stackblitz 你的代码吗??

标签: angular


【解决方案1】:

这并不准确,但我认为使用异步验证器(请参阅docs)可以解决您的问题。 asyncValidatros 的问题在于性能。如果您不使用 updateOn 'blur' 或 'submit' Angular 每次更改表单时都会调用。

假设你有一个服务,它返回一个可观察的真或假,比如

@Injectable({ providedIn: 'root' })
export class ApiService {
  getWebName(webName: string): Observable<boolean> {
    const isTaken = webName=="Vivek Kumar";
    return of(isTaken).pipe(delay(1000));
  }
}

您需要使用 FormGroup 和 FormControl 的构造函数创建 formGroup 以指示何时进行验证。使用 FormBuilder 是不可能的

this.testForm = new FormGroup(
  {
    name: new FormControl("Vivek Kumar", {
      asyncValidators: this.checkIfNotRegister(),
      validators: Validators.required, 
      updateOn: 'blur'
    }),
    age: new FormControl(30, {
       validators:Validators.required,
       updateOn: 'blur'
    })
  }
);

我们的函数“checkIfNotRegister”是

checkIfNotRegister(): AsyncValidatorFn {
    return (control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => {
      return this.service.getWebName(control.value).pipe(
        map(res => res ? { repeat: "name yet register" } : null)
      )
    };
  }

而 .html 就像

<form [formGroup]="testForm">
    <mat-form-field class="name" appearance="outline">
        <input matInput placeholder="Name" formControlName="name">
    <mat-error *ngIf="testForm.get('name').hasError('required')">
      Name is required*
    </mat-error>
    <mat-error *ngIf="testForm.get('name').hasError('repeat')">
      Unknown server Error
    </mat-error>
    <mat-hint *ngIf="testForm.get('name').pending">Validating...</mat-hint>
  </mat-form-field>

  <mat-form-field class="age" appearance="outline">
        <input matInput placeholder="Age" formControlName="age">
    <mat-error *ngIf="testForm.get('age').hasError('required')">
      Age is required*
    </mat-error>
  </mat-form-field>

  <div>
    <button type="submit" (click)="submitForm()">Submit</button>
  </div>
</form>

看看我们如何使用&lt;mat-hint&gt; 来显示何时检查可观察对象

更新只检查 submit() 中的异步验证器

如果我们提交一些类似的内容:

  submitForm() {
    if (this.testForm.valid)
    {
      //Add an async validators
      this.testForm.get('name').setAsyncValidators(this.checkIfNotRegister());
      //force Angular to updateValueAndValidity
      this.testForm.get('name').updateValueAndValidity();
      //remove the async validator
      this.testForm.get('name').setAsyncValidators(null);
    }
  }

2019 年 6 月 27 日更新

但这不等待检查是否有效,所以需要再做一步它订阅this.testForm.statusChanges,所以我们的submitForm变成了

submitForm() {
    if (this.testForm.valid) {
      this.testForm.statusChanges.pipe(take(2),last()).subscribe(res=>{
          //if res=='VALID' make something
          //if res=='INVALID'we don't need make nothing
          console.log(res)
      })
      this.testForm.get('name').setAsyncValidators(this.checkIfNotRegister());
      this.testForm.get('name').updateValueAndValidity({onlySelf:false,emitEvent:true});
      this.testForm.get('name').setAsyncValidators(null);
    }

我们的表单不需要验证器 onBlur 或 onSubmit

this.testForm = new FormGroup(
      {
        name: new FormControl("Vivek Kumar", Validators.required),
        age: new FormControl(30, Validators.required)
      }
    );

你可以在stackblitz看到最终结果

【讨论】:

  • 嗨@eliseo,非常感谢您的回复。但 asyncValidator 将在 blur 事件上自动触发。我的要求是在提交表单后触发验证,这可能是多个字段出现错误的情况。
  • ::glups:: 这是真的......但是......我只是更新了堆栈闪电战和答案。我的解决方案是,在提交时,创建一个 setAsyncValidators 并创建一个 updateValueAndValidity(),查看我的答案更新
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-05
  • 2017-09-17
  • 2019-02-24
  • 2020-07-27
  • 2019-05-18
  • 2021-07-24
  • 1970-01-01
相关资源
最近更新 更多