[英]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.