自定义密码匹配验证器在 angular5 中不起作用

Posted

技术标签:

【中文标题】自定义密码匹配验证器在 angular5 中不起作用【英文标题】:Custom password match validator is not working in angular5 【发布时间】:2019-05-28 23:01:21 【问题描述】:

我正在实现自定义验证器以匹配组件中的密码。

这是我的 component.ts 表单声明

this.addUserForm = new FormGroup(
  firstname: new FormControl('', [Validators.required]),
  lastname: new FormControl('', [Validators.required]),
  city: new FormControl(),
  address: new FormControl(),
  email: new FormControl('', [Validators.required, Validators.email]),
  password: new FormControl('', [Validators.required, Validators.minLength(6)]),
  confirm_password: new FormControl('', [Validators.required, ConfirmPasswordValidator.MatchPassword]),
  role: new FormControl('', [Validators.required]),
  phone: new FormControl(),
  companyCode: new FormControl(this.local_storage.getCurrentUser().companyCode, [Validators.required])
);

这是我的 custom.validator.ts

import  AbstractControl  from '@angular/forms';

export class ConfirmPasswordValidator 
static MatchPassword(control: AbstractControl) 
    let password = control.get('password').value;
    let confirmPassword = control.get('confirm_password').value;

    if (password != confirmPassword) 
        console.log('false')
        control.get('confirmPassword').setErrors( ConfirmPassword: true );
     else 
        return null
    
  
 

这是我的 component.html 输入部分

 <label class="col-form-label">Password</label>
        <div class="form-group row">
          <div class="col-sm-10">
            <input type="password" class="form-control" formControlName="password">
            <div class="alert alert-danger" *ngIf="addUserForm.get('password').touched && addUserForm.get('password').invalid && addUserForm.get('password').errors.required">
              Password is required
            </div>
            <div class="alert alert-danger" *ngIf="addUserForm.get('password').touched && addUserForm.get('password').invalid && addUserForm.get('password').errors.minlength && !addUserForm.get('password').errors.required">
              Password length must be greater than 6
            </div>
          </div>
        </div>
       <div class="alert alert-danger" *ngIf="addUserForm.get('confirm_password').touched && addUserForm.get('confirm_password').invalid && addUserForm.get('confirm_password').errors.ConfirmPassword">
              Password deesn't match
          </div>

但它给出了这个错误 property 'value' of null TypeError: Cannot read property 'value' of null at ConfirmPasswordValidator.MatchPassword (user.validator.ts:5) 项目结构和目录非常复杂和庞大,这就是为什么不能共享所有组件和 html 代码的原因。 我的代码有什么问题?

【问题讨论】:

【参考方案1】:

表单组验证器

更新 MatchPassword 以在表单组级别上工作,因此您无需向 confirmPassword 控件添加自定义验证器

static MatchPassword(control: AbstractControl) 
    let password = control.get('password').value;
    let confirmPassword = control.get('confirm_password').value;

    if (password != confirmPassword) 
      return  ConfirmPassword: true ;
     else 
        return null
    
  

并为 formGroup 验证器选项添加此验证器

 validators: ConfirmPasswordValidator.MatchPassword 

stackblitz demo??

表单控件验证器

如果你想给控件添加验证,那么控件参数将是确认密码控件,你需要使用父级访问表单组并获取密码控件的值

this.form = fb.group(
  password: [null, [Validators.required]],
  confirm_password: [null, [Validators.required, MatchPassword]]
)

匹配密码验证器

function MatchPassword(control: AbstractControl) 
  let parent = control.parent
  if (parent) 
    let password = parent.get('password').value;
    let confirmPassword = control.value;

    if (password != confirmPassword) 
      return  ConfirmPassword: true ;
     else 
      return null
    
   else 
    return null;
  

stackblitz demo??

【讨论】:

第二种解决方案不好,因为验证器只会在您更改确认密码值时调用,而不是在修改密码值时。 谢谢。你的例子对我有用。我根据需要修改了您的示例。 现在我看到验证器将在控制更改上工作的错误,所以如果我更改密码,确认仍然有效@每次密码值改变?? @JBNizet【参考方案2】:

您的代码有几个问题。

首先:您从名为“password”的控件中获取一个子控件,并从传递给验证器的控件中获取另一个名为“confirmPassword”的子窗体控件。所以验证器应该验证的是一个FormGroup,包含这两个表单控件。但是您没有在表单组上设置此验证器。您将它设置在表单控件confirmPassword 上。您需要在封闭的表单组上设置此验证器。

第二:验证器不应该修改它正在验证的控件。它的唯一责任是返回错误(如果没有错误,则返回 null)。 Angular 将根据您返回的内容设置控件的有效性。所以它的代码应该是

static MatchPassword(control: AbstractControl) 
  const password = control.get('password').value;
  const confirmPassword = control.get('confirm_password').value;

  if (password != confirmPassword) 
    return  ConfirmPassword: true ;
   else 
    return null;
  

或者,写得更简洁:

static MatchPassword(control: AbstractControl) 
  return control.get('password').value != control.get('confirm_password').value ?  ConfirmPassword: true  : null;

【讨论】:

我在谷歌上没有找到如何在 FormGroup 中放置验证器。你能告诉我如何在 FormGroup 上指定验证器吗? 阅读 api 文档和/或有关表单验证的官方指南:angular.io/api/forms/FormGroup, angular.io/guide/form-validation#adding-to-reactive-forms-1 我根据您的指南更新了我的帖子,但仍然出现同样的错误。请看我更新的帖子我更新了代码 验证器仍设置在 ConfirmPassword 字段上。我已经回滚了您对问题的更改,因为如果您将问题中的代码修复了一半,我的回答就没有意义。 我更新了我的代码。现在没有发生错误,并且在控制台中它也是错误的,但在模板警告中没有显示。我在 *ngIF 中的情况有问题吗?

以上是关于自定义密码匹配验证器在 angular5 中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的自定义验证器在 parsley.js 中不起作用?

自定义对象验证在 Nestjs DTO 中不起作用

身份验证在 yii2 中不起作用

AngularJS 自定义表单验证指令在我的模式中不起作用

ASP.NET 2.0 自定义客户端验证在 Internet Explorer 中不起作用

自定义授权过滤器在 ASP.NET Core 3 中不起作用