实际应用中的角形式验证

问题描述 投票:1回答:3

我的问题的目的是找出它是否必须很复杂,或者我做错了什么。

很容易显示出表单验证对本教程的作用。但是,当涉及到现实生活中的应用程序时,事情就变得复杂了。我从一个简单的注册表开始]

  • 用户名
  • 电子邮件
  • 密码
  • 重复的密码

如果我使用类似教程的方法,那么我将使用*ngIf显示出现在相应输入上方的所有类型的错误。问题在于,这会导致糟糕的用户体验:

  • 显示和隐藏使输入跳跃的错误
  • 如果我有很多密码验证条件,那么用户会得到一长串错误
  • 表格开始看起来像是一个大警告,并不简洁
  • 重复的密码大喊它与密码不同,尽管用户还没有输入任何东西

此外,如果不触摸表单,为了停止显示错误,则需要在模板的整个位置添加这样的代码

myForm.get('controlName').invalid && (myForm.get('controlName').dirty || myForm.get('controlName').touched)

什么开始类似于PHP意大利面条代码。

我想说的是,即使是非常简单的形式,如果要创造良好的用户体验,逻辑也会变得非常复杂。到目前为止,我已经完成了一个逻辑,该逻辑在组件中扫描特定控件的错误并一次仅返回一个错误。

您的经历是什么?您有什么建议或最佳做法的例子吗?

angular angular-forms angular-validation
3个回答
2
投票

Angular 2+中提供了两种类型的表单。

  1. 模板驱动的形式,与Angularjs 1.x非常相似
  2. 反应式表单,为复杂的逻辑提供程序化表单处理,例如自定义验证和元素之间的验证。

为了验证您的情况下的passwordrepeated password,使用Reactive Forms时,您可以创建包装器FormGroup来对这两个表单元素进行分组。

this.email = new FormControl('', [Validators.required, this.validateEmail]);
    this.username = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);
    this.password = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);
    this.passwordConfirm = new FormControl('', [Validators.required, Validators.minLength(6), Validators.maxLength(20)]);

    this.passwordGroup = fb.group(
      {
        password: this.password,
        passwordConfirm: this.passwordConfirm
      },
      { validator: this.passwordMatchValidator }
    );

    this.signupForm = fb.group({
      email: this.email,
      username: this.username,
      passwordGroup: this.passwordGroup
    });

并使用本地函数来验证密码组或使用自定义指令。

passwordMatchValidator(g: FormGroup) {
    return g.get('password').value === g.get('passwordConfirm').value
      ? null : { 'mismatch': true };
  }

如果验证失败,则在模板文件中添加一个指示器。

<div class="col-md-12" [class.has-danger]="passwordGroup.invalid">
              <div class="form-control-feedback" *ngIf="passwordGroup.invalid">
                <p *ngIf="passwordGroup.hasError('mismatch')">Passwords are mismatched.</p>
              </div>
            </div>

从我的Github中检查sample codes。并阅读Handling formsprocessing auth的页面以了解详细信息。


1
投票

您可以使用带有垫误差选项的角度材料输入,该选项可以非常简洁地显示误差。您可以在https://material.angular.io上查看官方文档,以详细了解mat-error和mat-h​​int。您只需使用如下所示的方法来显示错误: <form [formGroup]="form" (ngSubmit)="onSubmit()"> <mat-form-field> <input matInput type="text" formControlName="username" name="email" placeholder="E-Mail" #email required> <mat-error id="repeat-help" class="text-warning" *ngIf="!(form.controls.username.valid || form.controls.username.pristine)"> Please enter a valid e-mail ID </mat-error> </mat-form-field>

您可以使用反应形式来制作一个好的UI。


0
投票

我了解您的问题。如果表单具有许多经过验证的控件,则在模板中设置错误消息可能会造成混乱。我建议您将所有错误检查都移至组件文件。检查我做的这个Stackblitz:https://stackblitz.com/edit/angular-dugfod。它基于Deborah Kurata's excelente course about reactive forms at Pluralsight(在编写此答案时,该课程免费提供。)

Stackblitz示例中的要点如下:

1)为每个经过验证的控件创建以下形式的错误消息数组:

  private validationMessages = [
    {
      controlName: 'name',
      messages: { required: 'Name is required', minlength: 'Min length 3' }, 
      message: '' // for the actual message to be shown in the form
    },
    {
      controlName: 'country',
      messages: { countryNot: "Country can't be England" },
      message: ''
    },

2)创建一个检查控件是否有错误的函数,并在数组中设置相关的错误消息:

  setMessage(controlName: string) {
    let control = this.form.get(controlName);
    const val = this.validationMessages.filter(x => x.controlName === controlName)[0];
    val.message = '';

    if (control.errors) {
      val.message = Object.keys(control.errors)
        .map(key => val.messages[key]).join(' ');
    }
  }

3)在ngOnInit方法中,设置Observable以跟踪已验证控件的更改,并为每次更改值调用setMessage函数:

    const fields = ['name', 'country', 'numberOfPlayers', 'coach', 'playerLimitsGroup.minPlayers',
      'playerLimitsGroup.maxPlayers', 'playerLimitsGroup'];
    fields.forEach(field => {
      const control = this.form.get(field);
      control.valueChanges.subscribe(
        () => this.setMessage(field)
      );
      this.setMessage(field); // set the initial error messages for demonstration
    });

4)创建一种方法来获取控件的当前错误消息。请注意,您可以在此处决定是要始终显示错误消息,还是仅在控件变脏或触摸时才显示错误消息:

  getMessage(controlName: string) {
    let control = this.form.get(controlName);
    let hideCleanErrors = this.form.get('hideCleanErrors').value;
    if (control.dirty || control.touched || !hideCleanErrors) {
      return this.validationMessages.filter(x => x.controlName === controlName)[0].message;
    }
    return '';
  }

5)现在,您有一种巧妙的方法来显示模板中每个控件的错误消息:

    <label>Name:
      <input type="text" formControlName="name">
    </label>
    <span>{{getMessage('name')}}</span>

另外,我的Stackblitz示例演示了几种设置带有或不带有参数的自定义验证器,跨域验证以及在运行时设置验证器的方法。

© www.soinside.com 2019 - 2024. All rights reserved.