Angular 未显示反应式 md 错误的自定义验证器

Angular custom validator for reactive form md-error not showing

如果密码不匹配,我无法显示我的 *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
      }
    };
  }

@编辑 使用简单的 <span> 而不是 <md-error> 似乎可以解决问题。

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

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

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

md-error inside 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

但是有了这个,你真的无法控制它何时被触发。尽管使用您目前拥有的代码,只要 any 发生变化,您的自定义验证器也会被触发。然后,检查下面的 旁注


旁注

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

至于 repeat 表单控件,除了检查它是否与 password 字段匹配之外,我认为没有必要使用任何其他验证。