Angular 2 匹配表单中的密码
Angular 2 Match password in a form
我知道其他时候也有人以类似的形式问过这个问题,但我的情况有点不同;让我解释一下:
我有一个重设密码表单,有 3 个字段(旧密码、新密码、确认密码)。当然,我需要检查提交的密码是否等于提交的确认密码,我想在单击提交之前执行此操作。我定义的形式如下(在component.ts中)
this.form = fb.group({
// define your control in you form
oldpassword: ['', Validators.required],
password: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(10)]],
confirmPassword: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(10)]]
}, {
validator: PasswordValidation.MatchPassword // your validation method
});
export class PasswordValidation {
static MatchPassword(AC: AbstractControl) {
const password = AC.get('password').value; // to get value in input tag
const confirmPassword = AC.get('confirmPassword').value; // to get value in input tag
if (password !== confirmPassword) {
AC.get('confirmPassword').setErrors({MatchPassword: true})
} else {
return null
}
}
}
这是问题所在,如果我在编译 "new password" 之前更改 "confirm password field",则表格无效。换句话说,如果我尊重字段的垂直顺序,一切都可以,但如果我按不同的顺序编译字段,那么表单仍然无效。
这里是 html 代码:(如您所见,它有点令人困惑,因为我有其他 UX 约束 ehich 对应于用户可能的交互)
<form [formGroup]="form" novalidate (ngSubmit)="modal.open()">
<div class="form-group">
<label for="oldpassword">Inserisci vecchia password</label>
<input type="password" id="oldpassword" class="form-control" formControlName="oldpassword">
<div
*ngIf="form.controls['oldpassword'].hasError('required') && form.controls['oldpassword'].touched"
class="alert alert-danger">
Campo obbligatorio
</div>
</div>
<div class="form-group">
<label for="password">Inserisci nuova password</label>
<input type="password" id="password" class="form-control" formControlName="password">
<div *ngIf="form.controls['password'].hasError('required') && form.controls['password'].touched"
class="alert alert-danger">
Campo obbligatorio
</div>
<div *ngIf="form.controls['password'].hasError('minlength') && form.controls['password'].touched"
class="alert alert-danger">
Lunghezza minima: 4 caratteri.
</div>
</div>
<div class="form-group">
<label for="confirmPassword">Ripeti nuova password</label>
<input type="password" class="form-control" id="confirmPassword" formControlName="confirmPassword">
<div class="alert alert-danger"
*ngIf="form.errors?.MatchPassword || (form.controls['confirmPassword'].hasError('required') && form.controls['confirmPassword'].touched)">
Le password non corrispondono
</div>
</div>
<div *ngIf="!this.state.controlloIn; else elseBlock">
<button type="submit" class="btn btn-primary btn-update" [disabled]="!form.valid || this.controlloInvia">
Invia Richiesta
</button>
</div>
<ng-template #elseBlock>
<button type="submit" class="btn btn-primary btn-update" [disabled]="true">
Invia Richiesta
</button>
</ng-template>
</form>
我不是 angular 专家,所以如果您能给我建议其他最佳实践,我将非常高兴。感谢大家
this.profileForm = this.formBuilder.group({
password: [this.profile.password, [
Validators.required,
Validators.minLength(4)]
],
passwordCheck: [this.profile.password, [
Validators.required,
Validators.minLength(4)
]],
oldPassword: [this.profile.oldPassword, [
Validators.required]],
}, { validator: matchingPasswordsValidator('password', 'passwordCheck') });
这是我用于更改密码的表格。
它使用一个单独的验证器,该验证器不验证它验证整个表单的字段。
export function matchingPasswordsValidator(passwordKey: string, confirmPasswordKey: string) {
return (group: FormGroup): { [key: string]: any } => {
let password = group.controls[passwordKey];
let confirmPassword = group.controls[confirmPasswordKey];
if (password.value !== confirmPassword.value) {
return {
mismatchedPasswords: true
};
}
}
}
@Directive({
selector: '[appMatchingPasswordsValidator]',
providers: [{
provide: NG_VALIDATORS, useExisting: MatchingPasswordsValidatorDirective, multi: true
}]
})
export class MatchingPasswordsValidatorDirective {
constructor() { }
validate(c: AbstractControl) {
matchingPasswordsValidator("test", "test");
}
}
那么这就是用来匹配密码的指令。或您在表格中提供的任何 2 个键。
您正在直接在确认字段中设置错误。如果您不再触摸该字段,则会在其上设置错误并且永远不会被删除。 Angular 运行 验证器仅针对已编辑的字段,因为您可以合理地认为如果某个字段被标记为错误且未被编辑,它仍处于错误状态。
我建议您将此错误直接放在 FormGroup
上:
static MatchPassword(AC: AbstractControl) {
const password = AC.get('password').value; // to get value in input tag
const confirmPassword = AC.get('confirmPassword').value; // to get value in input tag
if (password !== confirmPassword) {
return {MatchPassword: true};
} else {
return null
}
}
<div class="alert alert-danger"
*ngIf="form.errors?.MatchPassword || (form.controls['confirmPassword'].hasError('required') && form.controls['confirmPassword'].touched)">
Le password non corrispondono
</div>
我刚刚 运行 解决了这个问题并找到了不同的修复方法。当密码匹配时,我在返回 null 之前调用 AbstractFormControl 的 updateValueAndValidity 函数(onlySelf 为真,emitEvent 为假)。这使我能够对密码和确认密码输入进行验证。我可以在密码前输入确认密码,验证状态正常显示。
static MatchPassword(AC: AbstractControl) {
const password = AC.get('password').value;
const confirmPassword = AC.get('confirmPassword').value;
if (password !== confirmPassword) {
AC.get('confirmPassword').setErrors({MatchPassword: true})
} else {
AC.get('confirmPassword').updateValueAndValidity(
{onlySelf: true, emitEvent: false}
);
return null;
}
}
我知道这是对您问题的迟到回答,但我想展示一种方法。
您可以通过在 ngModel
.
上调用 .value
来比较输入值
您可以在下面的代码块中看到它是如何工作的
<div *ngIf="newPassword.dirty || newPassword.touched">
<div class="alert alert-danger" *ngIf="newPassword.value.match(passwordCurrent.value)">
Current password and New Password can't match.
</div>
</div>
长版代码
<div class="form-group">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i
class="fa fa-unlock-alt"></i></span>
</div>
<input required minlength="6" [(ngModel)]="passwordOneIn"
#newPassword="ngModel" name="newPassword" class="form-control"
placeholder="New Password" type="password">
</div>
</div>
<!--#####check if the password and current password match########-->
<div *ngIf="newPassword.dirty || newPassword.touched">
<div class="alert alert-danger" *ngIf="newPassword.value.match(passwordCurrent.value)">
Current password and New Password can't match.
</div>
</div>
<div *ngIf="newPassword.invalid && (newPassword.dirty || newPassword.touched)"
class="alert alert-danger">
<div *ngIf="newPassword.errors.required">
password is required.
</div>
</div>
<div class="form-group">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-unlock-alt"></i></span>
</div>
<input required minlength="6" [(ngModel)]="passwordTwoIn"
#retypedPassword="ngModel" name="retypedPassword"
class="form-control" placeholder="Retype Password" type="password">
</div>
</div>
<div *ngIf="retypedPassword.invalid && (retypedPassword.dirty || retypedPassword.touched)"
class="alert alert-danger">
<div *ngIf="retypedPassword.errors.required">
password is required.
</div>
</div>
<!--##### check if the new password and retyped password match ########-->
<div *ngIf="retypedPassword.dirty || retypedPassword.touched">
<div class="alert alert-danger" *ngIf="!newPassword.value.match(retypedPassword.value)">
New password and Retyped Password don't match.
</div>
</div>
<button [disabled]="changePasswordFrom.form.invalid || newPassword.value.match(passwordCurrent.value) || !newPassword.value.match(retypedPassword.value)"
type="submit" class="btn btn-primary mt-4">Change Password</button>
</div>
我知道其他时候也有人以类似的形式问过这个问题,但我的情况有点不同;让我解释一下:
我有一个重设密码表单,有 3 个字段(旧密码、新密码、确认密码)。当然,我需要检查提交的密码是否等于提交的确认密码,我想在单击提交之前执行此操作。我定义的形式如下(在component.ts中)
this.form = fb.group({
// define your control in you form
oldpassword: ['', Validators.required],
password: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(10)]],
confirmPassword: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(10)]]
}, {
validator: PasswordValidation.MatchPassword // your validation method
});
export class PasswordValidation {
static MatchPassword(AC: AbstractControl) {
const password = AC.get('password').value; // to get value in input tag
const confirmPassword = AC.get('confirmPassword').value; // to get value in input tag
if (password !== confirmPassword) {
AC.get('confirmPassword').setErrors({MatchPassword: true})
} else {
return null
}
}
}
这是问题所在,如果我在编译 "new password" 之前更改 "confirm password field",则表格无效。换句话说,如果我尊重字段的垂直顺序,一切都可以,但如果我按不同的顺序编译字段,那么表单仍然无效。
这里是 html 代码:(如您所见,它有点令人困惑,因为我有其他 UX 约束 ehich 对应于用户可能的交互)
<form [formGroup]="form" novalidate (ngSubmit)="modal.open()">
<div class="form-group">
<label for="oldpassword">Inserisci vecchia password</label>
<input type="password" id="oldpassword" class="form-control" formControlName="oldpassword">
<div
*ngIf="form.controls['oldpassword'].hasError('required') && form.controls['oldpassword'].touched"
class="alert alert-danger">
Campo obbligatorio
</div>
</div>
<div class="form-group">
<label for="password">Inserisci nuova password</label>
<input type="password" id="password" class="form-control" formControlName="password">
<div *ngIf="form.controls['password'].hasError('required') && form.controls['password'].touched"
class="alert alert-danger">
Campo obbligatorio
</div>
<div *ngIf="form.controls['password'].hasError('minlength') && form.controls['password'].touched"
class="alert alert-danger">
Lunghezza minima: 4 caratteri.
</div>
</div>
<div class="form-group">
<label for="confirmPassword">Ripeti nuova password</label>
<input type="password" class="form-control" id="confirmPassword" formControlName="confirmPassword">
<div class="alert alert-danger"
*ngIf="form.errors?.MatchPassword || (form.controls['confirmPassword'].hasError('required') && form.controls['confirmPassword'].touched)">
Le password non corrispondono
</div>
</div>
<div *ngIf="!this.state.controlloIn; else elseBlock">
<button type="submit" class="btn btn-primary btn-update" [disabled]="!form.valid || this.controlloInvia">
Invia Richiesta
</button>
</div>
<ng-template #elseBlock>
<button type="submit" class="btn btn-primary btn-update" [disabled]="true">
Invia Richiesta
</button>
</ng-template>
</form>
我不是 angular 专家,所以如果您能给我建议其他最佳实践,我将非常高兴。感谢大家
this.profileForm = this.formBuilder.group({
password: [this.profile.password, [
Validators.required,
Validators.minLength(4)]
],
passwordCheck: [this.profile.password, [
Validators.required,
Validators.minLength(4)
]],
oldPassword: [this.profile.oldPassword, [
Validators.required]],
}, { validator: matchingPasswordsValidator('password', 'passwordCheck') });
这是我用于更改密码的表格。 它使用一个单独的验证器,该验证器不验证它验证整个表单的字段。
export function matchingPasswordsValidator(passwordKey: string, confirmPasswordKey: string) {
return (group: FormGroup): { [key: string]: any } => {
let password = group.controls[passwordKey];
let confirmPassword = group.controls[confirmPasswordKey];
if (password.value !== confirmPassword.value) {
return {
mismatchedPasswords: true
};
}
}
}
@Directive({
selector: '[appMatchingPasswordsValidator]',
providers: [{
provide: NG_VALIDATORS, useExisting: MatchingPasswordsValidatorDirective, multi: true
}]
})
export class MatchingPasswordsValidatorDirective {
constructor() { }
validate(c: AbstractControl) {
matchingPasswordsValidator("test", "test");
}
}
那么这就是用来匹配密码的指令。或您在表格中提供的任何 2 个键。
您正在直接在确认字段中设置错误。如果您不再触摸该字段,则会在其上设置错误并且永远不会被删除。 Angular 运行 验证器仅针对已编辑的字段,因为您可以合理地认为如果某个字段被标记为错误且未被编辑,它仍处于错误状态。
我建议您将此错误直接放在 FormGroup
上:
static MatchPassword(AC: AbstractControl) {
const password = AC.get('password').value; // to get value in input tag
const confirmPassword = AC.get('confirmPassword').value; // to get value in input tag
if (password !== confirmPassword) {
return {MatchPassword: true};
} else {
return null
}
}
<div class="alert alert-danger"
*ngIf="form.errors?.MatchPassword || (form.controls['confirmPassword'].hasError('required') && form.controls['confirmPassword'].touched)">
Le password non corrispondono
</div>
我刚刚 运行 解决了这个问题并找到了不同的修复方法。当密码匹配时,我在返回 null 之前调用 AbstractFormControl 的 updateValueAndValidity 函数(onlySelf 为真,emitEvent 为假)。这使我能够对密码和确认密码输入进行验证。我可以在密码前输入确认密码,验证状态正常显示。
static MatchPassword(AC: AbstractControl) {
const password = AC.get('password').value;
const confirmPassword = AC.get('confirmPassword').value;
if (password !== confirmPassword) {
AC.get('confirmPassword').setErrors({MatchPassword: true})
} else {
AC.get('confirmPassword').updateValueAndValidity(
{onlySelf: true, emitEvent: false}
);
return null;
}
}
我知道这是对您问题的迟到回答,但我想展示一种方法。
您可以通过在 ngModel
.
.value
来比较输入值
您可以在下面的代码块中看到它是如何工作的
<div *ngIf="newPassword.dirty || newPassword.touched">
<div class="alert alert-danger" *ngIf="newPassword.value.match(passwordCurrent.value)">
Current password and New Password can't match.
</div>
</div>
长版代码
<div class="form-group">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i
class="fa fa-unlock-alt"></i></span>
</div>
<input required minlength="6" [(ngModel)]="passwordOneIn"
#newPassword="ngModel" name="newPassword" class="form-control"
placeholder="New Password" type="password">
</div>
</div>
<!--#####check if the password and current password match########-->
<div *ngIf="newPassword.dirty || newPassword.touched">
<div class="alert alert-danger" *ngIf="newPassword.value.match(passwordCurrent.value)">
Current password and New Password can't match.
</div>
</div>
<div *ngIf="newPassword.invalid && (newPassword.dirty || newPassword.touched)"
class="alert alert-danger">
<div *ngIf="newPassword.errors.required">
password is required.
</div>
</div>
<div class="form-group">
<div class="input-group input-group-alternative">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-unlock-alt"></i></span>
</div>
<input required minlength="6" [(ngModel)]="passwordTwoIn"
#retypedPassword="ngModel" name="retypedPassword"
class="form-control" placeholder="Retype Password" type="password">
</div>
</div>
<div *ngIf="retypedPassword.invalid && (retypedPassword.dirty || retypedPassword.touched)"
class="alert alert-danger">
<div *ngIf="retypedPassword.errors.required">
password is required.
</div>
</div>
<!--##### check if the new password and retyped password match ########-->
<div *ngIf="retypedPassword.dirty || retypedPassword.touched">
<div class="alert alert-danger" *ngIf="!newPassword.value.match(retypedPassword.value)">
New password and Retyped Password don't match.
</div>
</div>
<button [disabled]="changePasswordFrom.form.invalid || newPassword.value.match(passwordCurrent.value) || !newPassword.value.match(retypedPassword.value)"
type="submit" class="btn btn-primary mt-4">Change Password</button>
</div>