繁体   English   中英

使用 Angular 的密码确认表

[英]Password Confirmation Form Using Angular

我正在尝试编写一个表单,其中涉及在确认密码字段中确认新密码值的逻辑。 我几乎肯定这与我的逻辑在自定义验证器本身中的呈现方式有关:password.validators.ts。 在不放弃解决方案的情况下,我在验证 function 中的逻辑是否缺失? 我附上了我的模板、客户验证器文件和组件。 当我的自定义验证呈现为真时,我希望确认密码字段在我的模板中抛出一个错误,这种情况是新密码字段与确认密码字段不匹配。 当我 go 在字段中输入值时,什么都没有显示。

<form [formGroup]="form">
    <div class="form-group">
      <label for="oldPassword">Old Password</label>
      <input 
        formControlName="oldPassword" 
        type="password" 
        class="form-control" 
        id="oldPassword" 
        placeholder="Enter old password">
      <div 
        *ngIf="oldPassword.touched && oldPassword.invalid" 
        class="alert alert-danger"> 
            <div *ngIf="oldPassword.errors.required">Old password is required</div>
            <div *ngIf="oldPassword.errors.cannotContainOldPassword">Old password is not valid</div>
      </div>
    </div>
    <div class="form-group">
      <label for="newPassword">New Password</label>
      <input 
            formControlName="newPassword" 
            type="text" 
            class="form-control" 
            id="newPassword" 
            placeholder="Enter new password">
        <div 
            *ngIf="newPassword.touched && newPassword.invalid" 
            class="alert alert-danger"> 
                <div *ngIf="newPassword.errors.required">New password is required</div>
      </div>
    </div>
    <div class="form-group">
        <label for="confirmPassword">Confirm Password</label>
        <input 
            formControlName="confirmPassword" 
            type="text" 
            class="form-control" 
            id="confirmPassword" 
            placeholder="Confirm new Password">
        <div 
            *ngIf="confirmPassword.touched && confirmPassword.invalid" 
            class="alert alert-danger"> 
                <div *ngIf="confirmPassword.errors.required">Confirm password is required</div>
                <div *ngIf="confirmPassword.errors.confirmNewPassword">Passwords must match</div>
        </div>    
      </div>
    <button type="submit" class="btn btn-primary">Change Password</button>
  </form>
import { AbstractControl, ValidationErrors, ValidatorFn, Validators } from '@angular/forms';

export class PasswordValidators{

    //Make sure old password is correct
    static cannotContainOldPassword(control: AbstractControl) : Promise<ValidationErrors> | null {
        return new Promise((resolve, reject) => {
            setTimeout(()=>{
                if(control.value != "1234"){
                    resolve({cannotContainOldPassword: true});
                }else{
                    resolve(null);
                }
            });
        });
    }

    //Make sure passwords match
    static confirmNewPassword(control: AbstractControl): ValidationErrors | null{
        let newPass = control.get('newPassword');
        let confirmPass = control.get('confirmPassword');
        if(newPass === confirmPass){
            return null;
            //return { confirmNewPassword: true };
        }else{
            return { confirmNewPassword: true };
        }
    }
}
import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { PasswordValidators } from './password.validators';

@Component({
  selector: 'password-form-change',
  templateUrl: './password-form-change.component.html',
  styleUrls: ['./password-form-change.component.css']
})
export class PasswordFormChangeComponent {

  form = new FormGroup({
    oldPassword: new FormControl('', Validators.required, PasswordValidators.cannotContainOldPassword),
    newPassword: new FormControl('', Validators.required),
    confirmPassword: new FormControl('', [
      Validators.required, 
      PasswordValidators.confirmNewPassword
    ])
  })

  get oldPassword(){
    return this.form.get('oldPassword');
  }

  get newPassword(){
    return this.form.get('newPassword');
  }

  get confirmPassword(){
    return this.form.get('confirmPassword');
  }
  

}

问题

问题是您将验证器应用于 FormControl 本身,但在验证器内部,您尝试访问其子级(控件没有)。

form = new FormGroup({
  oldPassword: new FormControl(''),
  newPassword: new FormControl(''),
  // Here you apply the Validator to your control
  confirmPassword: new FormControl('', [PasswordValidators.confirmNewPassword])
})
static confirmNewPassword(control: AbstractControl): ValidationErrors | null{
  // Your control does not have children "newPassword" and "confirmPassword"
  let newPass = control.get('newPassword'); 
  let confirmPass = control.get('confirmPassword');
  if(newPass === confirmPass) { // You are comparing FormControls instead of their values 
    return null;
  } else {
    return { confirmNewPassword: true };
  }
}

解决方案

最简单的解决方案是将验证器移至表单组。 这也可能是首选解决方案,因为当“newPassword”或“confirmPassword”更改时,您的验证器将运行。

首先,修复您的验证器以检查值而不是比较控件本身:

static confirmNewPassword(control: AbstractControl): ValidationErrors | null{
  let newPass = control.get('newPassword').value; // add .value
  let confirmPass = control.get('confirmPassword').value; // add .value
  return newPass === confirmPass ? null : {confirmNewPassword: true };
}

然后将验证器应用于整个表单(组):

form = new FormGroup({
  oldPassword: new FormControl(''),
  newPassword: new FormControl(''),
  // Here you apply the Validator to your control
  confirmPassword: new FormControl('')
}, {validators: PasswordValidators.confirmNewPassword}) // Add the validator to the group instead of your control

最后,调整您的模板以检查表单(组)而不是您的控件上的错误:

<div class="form-group">
  <label for="confirmPassword">Confirm Password</label>
  <input 
    formControlName="confirmPassword" 
    type="text" 
    class="form-control" 
    id="confirmPassword" 
    placeholder="Confirm new Password">
  <div 
    *ngIf="confirmPassword.touched && confirmPassword.invalid" 
    class="alert alert-danger"
  > 
    <div *ngIf="confirmPassword.errors?.required">Confirm password is required</div>
    <!--                              ^                    -->
    <!-- Access the errors object by using ?, since errors is null when no error is present -->
    <div *ngIf="form.errors?.confirmNewPassword">Passwords must match</div>
    <!--        ^^^^        -->
    <!-- Check for errors on form here, instead of the control -->
  </div>    
</div>

这里有一个 Stackblitz ,上面有一个最小的例子。

问题出在我模板中的 ngIf 指令中。 问题是,只要我在 Confirm Password 字段中输入内容, *ngIf="confirmPassword.touched && confirmPassword.invalid" 就会呈现为 true,因此该父 div 下的两个错误都会 go 消失。 所以解决方案是在下面插入另一个 div 进行密码验证。 这 ”?” 必须包含运算符,否则它将抛出“错误类型错误:无法读取属性 'confirmNewPassword' of null”。

<form [formGroup]="form">
    <div class="form-group">
      <label for="oldPassword">Old Password</label>
      <input 
        formControlName="oldPassword" 
        type="password" 
        class="form-control" 
        id="oldPassword" 
        placeholder="Enter old password">
      <div 
        *ngIf="oldPassword.touched && oldPassword.invalid" 
        class="alert alert-danger"> 
            <div *ngIf="oldPassword.errors.required">Old password is required</div>
            <div *ngIf="oldPassword.errors.cannotContainOldPassword">Old password is not valid</div>
      </div>
    </div>
    <div class="form-group">
      <label for="newPassword">New Password</label>
      <input 
            formControlName="newPassword" 
            type="text" 
            class="form-control" 
            id="newPassword" 
            placeholder="Enter new password">
        <div 
            *ngIf="newPassword.touched && newPassword.invalid" 
            class="alert alert-danger"> 
                <div *ngIf="newPassword.errors.required">New password is required</div>
      </div>
    </div>
    <div class="form-group">
        <label for="confirmPassword">Confirm Password</label>
        <input 
            formControlName="confirmPassword" 
            type="text" 
            class="form-control" 
            id="confirmPassword" 
            placeholder="Confirm new Password">
        <div 
            *ngIf="confirmPassword.touched && confirmPassword.invalid" 
            class="alert alert-danger"> 
                <div *ngIf="confirmPassword.errors.required">Confirm password is required</div>
        </div> 
        <div 
          *ngIf="confirmPassword.valid && form.invalid && form.errors?.confirmNewPassword" 
          class="alert alert-danger">
          Passwords should match
        </div>   
      </div>
    <button type="submit" class="btn btn-primary">Change Password</button>
  </form>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM