反应形式的角度自定义验证器md-error未显示

时间:2017-09-29 20:58:23

标签: angular validation angular-reactive-forms

如果密码不匹配,我无法显示*ngIf

<md-form-field>
    <input mdInput placeholder="Repeat password" type="password" formControlName="repeat">
    <md-error *ngIf="form.controls['repeat'].errors?.required">Field required</md-error>
    <md-error *ngIf="form.errors?.matchingPasswords">passwords don't match</md-error>
</md-form-field>

这是我的构造函数

  constructor(private formBuilder: FormBuilder) {
    this.form = this.formBuilder.group({
      username:
      ['',
        Validators.compose([
          Validators.required,
          Validators.minLength(3),
          Validators.maxLength(30),
          this.validateUsername,
          this.validateUsernameAvailability
        ])
      ],
      email:
      ['',
        Validators.compose([
          Validators.required,
          Validators.maxLength(30),
          this.validateEmail
        ])
      ],
      password:
      ['',
        Validators.compose([
          Validators.required,
          Validators.minLength(8),
          Validators.maxLength(30),
          this.validatePassword
        ])
      ],
      repeat: ['',
        Validators.compose([
          Validators.required
        ])
      ]
    }, {validator: this.matchingPasswords('password', 'repeat')});
  }

  matchingPasswords(password, repeat) {
    return (group: FormGroup) => {
      // Check if both fields are the same
      if (group.controls[password].value === group.controls[repeat].value) {
        return null; // Return as a match
      } else {
        return { 'matchingPasswords': true }; // Return as error: do not match
      }
    };
  }

Here's a screenshot

@EDIT 使用简单的<span>代替<md-error>似乎可以解决问题。

<span *ngIf="form.errors?.matchingPasswords">passwords don't match</span>

但为什么<md-error>出现?

1 个答案:

答案 0 :(得分:1)

似乎是需要解决方法的“ bug'

md-error内的

md-form-field只是验证了特定输入,不考虑任何其他输入。因此,如果您将移到之外的md-form-field它将验证,但当然css将在这种情况下搞砸了。修复是使用md-hint而只是使用css修改它来模拟md-error

<md-hint *ngIf="form.errors?.matchingPasswords">passwords don't match</md-hint>

只是扔掉那里你可以跳过自定义验证器并使用 Custom Error Matcher ,如下所示:

myErrorStateMatcher(control: FormControl): boolean {
  if(control.parent.controls.password.value === control.value) {
    control.setErrors(null)
    return false;
  }
  else {
    control.setErrors({notSame:true})
    return true;
  }
}
模板中的

<input mdInput formControlName="repeat" [errorStateMatcher]="myErrorStateMatcher">

<强> DEMO

但是有了这个,你真的无法控制何时被解雇。虽然使用您目前的代码,但只要发生任何更改,您的自定义验证程序也会被触发。有了它,请检查下面的侧注

侧注

如果使用md-hint,我会将passwordrepeat包装在嵌套表单组中,并将自定义验证程序应用于该嵌套表单组,以便仅在更改时触发发生在这两个表单控件中的任何一个。

对于repeat表单控件,我认为不需要使用任何其他验证,而是检查它是否与password字段匹配。