提交后在 Angular 的响应式表单上显示客户端错误和服务器错误

Posted

技术标签:

【中文标题】提交后在 Angular 的响应式表单上显示客户端错误和服务器错误【英文标题】:Display Client Errors and then Server Errors on Angular's Reactive Form after submission 【发布时间】:2021-10-05 07:36:49 【问题描述】:

使用 Angular 12 我有一个带有客户端和服务器验证的简单示例表单。

    我只想在第一次提交表单后显示客户端验证错误;

    客户端验证成功后,我会显示服务器验证错误。

    服务器验证错误在表单字段错误中添加为“不正确”字段。

    我正在使用响应式表单。

表单按预期工作,但我不确定我的实现是否是最佳选择。

组件的 HTML

<form [formGroup]="form">
  <label for="email">Email</label>
  <input id="email" type="text" formControlName="email">
  
  <span class="error" *ngIf="form.get('email')?.invalid && form.get('email')?.touched">
    form.get('email')?.errors?.incorrect
    <ng-container *ngIf="form.get('email')?.errors?.required">Email required</ng-container>
    <ng-container *ngIf="form.get('email')?.errors?.email">Invalid email</ng-container>
  </span>

  <button type="submit" (click)="send()" [disabled]="submitted">Send</button>
</form>

组件的打字稿

export class Component implements OnInit 

  form: FormGroup;
  submitted: boolean;

  constructor(private service: Service)  

    this.form = this.formBuilder.group( 
      email: ['', [Validators.required, Validators.email]],
    );

    this.submitted = false;

  

  send() 

    this.submitted = true;
    this.form.markAllAsTouched();

    if (this.form.valid) 

      this.service.send(email: this.form.value.email).subscribe(
        
        (next: Payload<Response>) =>  
          console.log("SUCCESS");
        ,

        (error) => 
          if (error.status === 400)
            new FormGroupErrorBuilder(this.form).setErrors(error.errors);
          this.submitted = false;
        

      );

     else 
      this.submitted = false;
    

      


FormGroupErrorBuilder

This is how I am adding server errors to Angular's FormGroup:

export class FormGroupErrorBuilder 

  formGroup: FormGroup;

  constructor(formGroup: FormGroup) 
    this.formGroup = formGroup;
  

  setErrors(errors: Error[]) 

    for (let error of errors) 

      var control = this.formGroup.get(error.name);

      if (control)
        control.setErrors( incorrect: error.message );
        
    

   

 

问题

    是否可以在首次提交时使用this.form.markAllAsTouched(); 对所有表单字段进行验证?

    使用条件*ngIf="form.get('email')?.invalid &amp;&amp; form.get('email')?.touched" 是显示表单字段错误的好选择吗?

欢迎任何改进代码的建议...

注意:

我正在使用submitted 变量来控制提交按钮是否被禁用并更改其 CSS 样式。

【问题讨论】:

【参考方案1】:

看看异步自定义验证器in the docs:

如果您使用选项 updateOption:'submit' 创建您的 formGroup,我认为您可以通过其他方式实现

有些喜欢:例如(我把validator放在FormGroup中,你可以放在自己的控件Email中)——那你应该改一下“validateEmail”函数。

this.form = this.formBuilder.group( 
  email: ['', [Validators.required, Validators.email]],
,updateOption:'submit',asyncValidator:this.validateEmail());


  validateEmail(): AsyncValidatorFn 
    return (group: FormGroup): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> => 
      return 
         this.service.send(email:group.value.email).map(res=>
            if (res.success)
                return null
            return  repeat: "name yet register" 
         )
      )))

    ;
  

注意:当您订阅该服务时,我在您的代码中看不清楚。您“捕获”错误,通常 API 返回一些类似 success:trueerror:'the email is yet!',但如果调用中没有错误,则不返回状态 400 - 您的 API 可以像上面一样响应但您收到响应成功,没有错误。

【讨论】:

我正在检查一些 API,当请求格式错误时,其中一些返回 400 错误。例如,当数据不正确时。当验证失败时,其他人似乎返回 HTTP 422 错误而不是 400。其他人按照您所说的进行操作并返回 HTTP 成功代码,但响应中有错误。我不确定哪个更好。 @MiguelMoura,如果你想在 subscribe(next) 中获得所有响应,你可以使用pipe(catchError(err=&gt;success:false)

以上是关于提交后在 Angular 的响应式表单上显示客户端错误和服务器错误的主要内容,如果未能解决你的问题,请参考以下文章

angular12表单错误提示不显示边框

怎么消除angular的表单验证

Angular 11 自定义 ISBN 验证器响应式表单

技术长文 | Angular 响应式表单在 K8S 资源上的实践

响应式表单-Angular高级编程

angular表单怎么验证输入最大小长度