在 Angular 中确认密码验证 6
Confirm password validation in Angular 6
我想使用material执行密码和确认密码验证仅限组件,如果 confirm password field doesn't match
和 if it is empty
, 确认密码 字段下方会显示一条错误消息。尝试了很多资源都无法实现。
也试过this video。
这是我正在寻找的 material 组件
HTML
<mat-form-field >
<input matInput placeholder="New password" [type]="hide ? 'password'
: 'text'" [formControl]="passFormControl" required>
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' :
'visibility_off'}}</mat-icon>
<mat-error *ngIf="passFormControl.hasError('required')">
Please enter your newpassword
</mat-error>
</mat-form-field>
<mat-form-field >
<input matInput placeholder="Confirm password" [type]="hide ?
'password' : 'text'" [formControl]="confirmFormControl"
required>
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' :
'visibility_off'}}</mat-icon>
<mat-error *ngIf="confirmFormControl.hasError('required')">
Confirm your password
</mat-error>
</mat-form-field>
TS
import {Component, OnInit } from '@angular/core';
import {FormControl, FormGroupDirective, NgForm, Validators} from
'@angular/forms';
import {ErrorStateMatcher} from '@angular/material/core';
@Component({
selector: 'asd-set-pass',
templateUrl: './set-pass.component.html',
styleUrls: ['./set-pass.component.css']
})
passFormControl = new FormControl('', [
Validators.required,
]);
confirmFormControl = new FormControl('', [
Validators.required,
]);
hide =true;
}
它正在验证以下条件
1) 如果密码和确认密码字段为空,则显示错误文本。
我想与 (.ts) 文件中的字段进行比较,例如它如何验证空字段,以及如果确认密码字段为空则出现错误。
这个问题可以结合这两个答案来解决: and
所以首先,您需要一个自定义验证程序来检查密码,它可能如下所示:
checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => {
let pass = group.get('password').value;
let confirmPass = group.get('confirmPassword').value
return pass === confirmPass ? null : { notSame: true }
}
并且您将为您的字段创建一个表单组,而不仅仅是两个表单控件,然后为您的表单组标记该自定义验证器:
this.myForm = this.fb.group({
password: ['', [Validators.required]],
confirmPassword: ['']
}, { validators: this.checkPasswords })
然后如其他答案中所述,mat-error
仅在 FormControl 无效时显示,因此您需要一个错误状态匹配器:
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const invalidCtrl = !!(control?.invalid && control?.parent?.dirty);
const invalidParent = !!(control?.parent?.invalid && control?.parent?.dirty);
return invalidCtrl || invalidParent;
}
}
在上面你可以调整何时显示错误信息。我只会在触摸 password
字段时显示消息。我也想在上面从 confirmPassword
字段中删除 required
验证器,因为如果密码不匹配,表单无论如何都无效。
然后在组件中,新建一个ErrorStateMatcher
:
matcher = new MyErrorStateMatcher();
最后,模板将如下所示:
<form [formGroup]="myForm">
<mat-form-field>
<input matInput placeholder="New password" formControlName="password" required>
<mat-error *ngIf="myForm.hasError('required', 'password')">
Please enter your new password
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Confirm password" formControlName="confirmPassword" [errorStateMatcher]="matcher">
<mat-error *ngIf="myForm.hasError('notSame')">
Passwords do not match
</mat-error>
</mat-form-field>
</form>
下面是使用上述代码的演示:StackBlitz
如果您不仅有密码和验证密码字段。
像这样,确认密码字段只会在用户在此字段上输入内容时突出显示错误:
validators.ts
import { FormGroup, FormControl, Validators, FormBuilder, FormGroupDirective, NgForm } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
export const EmailValidation = [Validators.required, Validators.email];
export const PasswordValidation = [
Validators.required,
Validators.minLength(6),
Validators.maxLength(24),
];
export class RepeatPasswordEStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
return (control && control.parent.get('password').value !== control.parent.get('passwordAgain').value && control.dirty)
}
}
export function RepeatPasswordValidator(group: FormGroup) {
const password = group.controls.password.value;
const passwordConfirmation = group.controls.passwordAgain.value;
return password === passwordConfirmation ? null : { passwordsNotEqual: true }
}
register.component.ts
import { FormGroup, FormControl, Validators, FormBuilder} from '@angular/forms';
import { EmailValidation, PasswordValidation, RepeatPasswordEStateMatcher, RepeatPasswordValidator } from 'validators';
...
form: any;
passwordsMatcher = new RepeatPasswordEStateMatcher;
constructor(private formBuilder: FormBuilder) {
this.form = this.formBuilder.group ( {
email: new FormControl('', EmailValidation),
password: new FormControl('', PasswordValidation),
passwordAgain: new FormControl(''),
acceptTerms: new FormControl('', [Validators.requiredTrue])
}, { validator: RepeatPasswordValidator });
}
...
register.component.html
<form [formGroup]="form" (ngSubmit)="submitAccount(form)">
<div class="form-content">
<div class="form-field">
<mat-form-field>
<input matInput formControlName="email" placeholder="Email">
<mat-error *ngIf="form.get('email').hasError('required')">
E-mail is mandatory.
</mat-error>
<mat-error *ngIf="form.get('email').hasError('email')">
Incorrect E-mail.
</mat-error>
</mat-form-field>
</div>
<div class="form-field">
<mat-form-field>
<input matInput formControlName="password" placeholder="Password" type="password">
<mat-hint class="ac-form-field-description">Between 6 and 24 characters.</mat-hint>
<mat-error *ngIf="form.get('password').hasError('required')">
Password is mandatory.
</mat-error>
<mat-error *ngIf="form.get('password').hasError('minlength')">
Password with less than 6 characters.
</mat-error>
<mat-error *ngIf="form.get('password').hasError('maxlength')">
Password with more than 24 characters.
</mat-error>
</mat-form-field>
</div>
<div class="form-field">
<mat-form-field>
<input matInput formControlName="passwordAgain" placeholder="Confirm the password" type="password" [errorStateMatcher]="passwordsMatcher">
<mat-error *ngIf="form.hasError('passwordsNotEqual')" >Passwords are different. They should be equal!</mat-error>
</mat-form-field>
</div>
<div class="form-field">
<mat-checkbox name="acceptTerms" formControlName="acceptTerms">I accept terms and conditions</mat-checkbox>
</div>
</div>
<div class="form-bottom">
<button mat-raised-button [disabled]="!form.valid">Create Account</button>
</div>
</form>
希望对您有所帮助!
我正在使用 angular 6,我一直在寻找匹配密码和确认密码的最佳方法。这也可用于匹配表单中的任意两个输入。我使用了 Angular 指令。我一直想用它们
ng g d compare-validators --spec false
and i will be added in your module. Below is the directive
import { Directive, Input } from '@angular/core';
import { Validator, NG_VALIDATORS, AbstractControl, ValidationErrors } from '@angular/forms';
import { Subscription } from 'rxjs';
@Directive({
// tslint:disable-next-line:directive-selector
selector: '[compare]',
providers: [{ provide: NG_VALIDATORS, useExisting: CompareValidatorDirective, multi: true}]
})
export class CompareValidatorDirective implements Validator {
// tslint:disable-next-line:no-input-rename
@Input('compare') controlNameToCompare;
validate(c: AbstractControl): ValidationErrors | null {
if (c.value.length < 6 || c.value === null) {
return null;
}
const controlToCompare = c.root.get(this.controlNameToCompare);
if (controlToCompare) {
const subscription: Subscription = controlToCompare.valueChanges.subscribe(() => {
c.updateValueAndValidity();
subscription.unsubscribe();
});
}
return controlToCompare && controlToCompare.value !== c.value ? {'compare': true } : null;
}
}
现在在你的组件中
<div class="col-md-6">
<div class="form-group">
<label class="bmd-label-floating">Password</label>
<input type="password" class="form-control" formControlName="usrpass" [ngClass]="{ 'is-invalid': submitAttempt && f.usrpass.errors }">
<div *ngIf="submitAttempt && signupForm.controls['usrpass'].errors" class="invalid-feedback">
<div *ngIf="signupForm.controls['usrpass'].errors.required">Your password is required</div>
<div *ngIf="signupForm.controls['usrpass'].errors.minlength">Password must be at least 6 characters</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="bmd-label-floating">Confirm Password</label>
<input type="password" class="form-control" formControlName="confirmpass" compare = "usrpass"
[ngClass]="{ 'is-invalid': submitAttempt && f.confirmpass.errors }">
<div *ngIf="submitAttempt && signupForm.controls['confirmpass'].errors" class="invalid-feedback">
<div *ngIf="signupForm.controls['confirmpass'].errors.required">Your confirm password is required</div>
<div *ngIf="signupForm.controls['confirmpass'].errors.minlength">Password must be at least 6 characters</div>
<div *ngIf="signupForm.controls['confirmpass'].errors['compare']">Confirm password and Password dont match</div>
</div>
</div>
</div>
希望这篇文章能帮到你
*此解决方案适用于反应式
您可能听说过确认密码被称为跨域验证。而我们平时写的字段级验证器只能应用于单个字段。对于跨文件验证,您可能必须编写一些父级验证器。对于具体的确认密码的情况,我宁愿这样做:
this.form.valueChanges.subscribe(field => {
if (field.password !== field.confirm) {
this.confirm.setErrors({ mismatch: true });
} else {
this.confirm.setErrors(null);
}
});
这是模板:
<mat-form-field>
<input matInput type="password" placeholder="Password" formControlName="password">
<mat-error *ngIf="password.hasError('required')">Required</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput type="password" placeholder="Confirm New Password" formControlName="confirm">`enter code here`
<mat-error *ngIf="confirm.hasError('mismatch')">Password does not match the confirm password</mat-error>
</mat-form-field>
我在 AJT_82 的回答中发现了一个错误。由于我没有足够的声誉在 AJT_82 的回答下发表评论,我必须 post 这个答案中的错误和解决方案。
这是错误:
解决方法:在下面的代码中:
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const invalidCtrl = !!(control && control.invalid && control.parent.dirty);
const invalidParent = !!(control && control.parent && control.parent.invalid && control.parent.dirty);
return (invalidCtrl || invalidParent);
}
}
将control.parent.invalid
更改为control.parent.hasError('notSame')
将解决此问题。
经过小改动,问题解决。
编辑:要仅在用户开始输入后验证“确认密码”字段,您可以 return 改为
return ((invalidCtrl || invalidParent) && control.valid);
我的回答很简单>我在 angular 6
中使用模板驱动创建了密码并确认了密码验证
我的 html 文件
<div class="form-group">
<label class="label-sm">Confirm Password</label>
<input class="form-control" placeholder="Enter Password" type="password" #confirm_password="ngModel" [(ngModel)]="userModel.confirm_password" name="confirm_password" required (keyup)="checkPassword($event)" />
<div *ngIf="confirm_password.errors && (confirm_password.dirty||confirm_password.touched||signup.submitted)">
<div class="error" *ngIf="confirm_password.errors.required">Please confirm your password</div>
</div>
<div *ngIf="i" class='error'>Password does not match</div>
</div>
我的打字稿文件
public i: boolean;
checkPassword(event) {
const password = this.userModel.password;
const confirm_new_password = event.target.value;
if (password !== undefined) {
if (confirm_new_password !== password) {
this.i = true;
} else {
this.i = false;
}
}
}
当点击提交按钮时,我检查我的值是真还是假
如果为真
if (this.i) {
return false;
}
else{
**form submitted code comes here**
}
您可以简单地使用密码字段值作为确认密码字段的模式。
例如:
<div class="form-group">
<input type="password" [(ngModel)]="userdata.password" name="password" placeholder="Password" class="form-control"
required #password="ngModel" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" />
<div *ngIf="password.invalid && (myform.submitted || password.touched)" class="alert alert-danger">
<div *ngIf="password.errors.required"> Password is required. </div>
<div *ngIf="password.errors.pattern"> Must contain at least one number and one uppercase and lowercase letter,
and at least 8 or more characters.</div>
</div>
</div>
<div class="form-group">
<input type="password" [(ngModel)]="userdata.confirmpassword" name="confirmpassword" placeholder="Confirm Password"
class="form-control" required #confirmpassword="ngModel" pattern="{{ password.value }}" />
<div *ngIf=" confirmpassword.invalid && (myform.submitted || confirmpassword.touched)" class="alert alert-danger">
<div *ngIf="confirmpassword.errors.required"> Confirm password is required. </div>
<div *ngIf="confirmpassword.errors.pattern"> Password & Confirm Password does not match.</div>
</div>
</div>
我是这样做的。希望对您有所帮助。
HTML :
<form [formGroup]='addAdminForm'>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Password</label>
<div class="col-sm-7">
<input type="password" class="form-control" formControlName='password' (keyup)="checkPassSame()">
<div *ngIf="addAdminForm.controls?.password?.invalid && addAdminForm.controls?.password.touched">
<p *ngIf="addAdminForm.controls?.password?.errors.required" class="errorMsg">*This field is required.</p>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Confirm Password</label>
<div class="col-sm-7">
<input type="password" class="form-control" formControlName='confPass' (keyup)="checkPassSame()">
<div *ngIf="addAdminForm.controls?.confPass?.invalid && addAdminForm.controls?.confPass.touched">
<p *ngIf="addAdminForm.controls?.confPass?.errors.required" class="errorMsg">*This field is required.</p>
</div>
<div *ngIf="passmsg != '' && !addAdminForm.controls?.confPass?.errors?.required">
<p class="errorMsg">*{{passmsg}}</p>
</div>
</div>
</div>
</form>
TS 文件:
export class AddAdminAccountsComponent implements OnInit {
addAdminForm: FormGroup;
password: FormControl;
confPass: FormControl;
passmsg: string;
constructor(
private http: HttpClient,
private router: Router,
) {
}
ngOnInit() {
this.createFormGroup();
}
// |---------------------------------------------------------------------------------------
// |------------------------ form initialization -------------------------
// |---------------------------------------------------------------------------------------
createFormGroup() {
this.addAdminForm = new FormGroup({
password: new FormControl('', [Validators.required]),
confPass: new FormControl('', [Validators.required]),
})
}
// |---------------------------------------------------------------------------------------
// |------------------------ Check method for password and conf password same or not -------------------------
// |---------------------------------------------------------------------------------------
checkPassSame() {
let pass = this.addAdminForm.value.password;
let passConf = this.addAdminForm.value.confPass;
if(pass == passConf && this.addAdminForm.valid === true) {
this.passmsg = "";
return false;
}else {
this.passmsg = "Password did not match.";
return true;
}
}
}
我最简单的方法:
(它也可以与电子邮件一起使用,例如)
public static matchValues(
matchTo: string // name of the control to match to
): (AbstractControl) => ValidationErrors | null {
return (control: AbstractControl): ValidationErrors | null => {
return !!control.parent &&
!!control.parent.value &&
control.value === control.parent.controls[matchTo].value
? null
: { isMatching: false };
};
}
在您的组件中:
this.SignUpForm = this.formBuilder.group({
password: [undefined, [Validators.required]],
passwordConfirm: [undefined,
[
Validators.required,
matchValues('password'),
],
],
});
跟进:
正如其他人在评论中指出的那样,如果您通过修复 password
字段来修复错误,错误不会消失,因为验证会在 passwordConfirm
输入上触发。这可以通过多种方式解决。我认为最好的是:
this.SignUpForm .controls.password.valueChanges.subscribe(() => {
this.SignUpForm .controls.confirmPassword.updateValueAndValidity();
});
关于 password
改变,revliadte confirmPassword
。
只要做一个标准的自定义验证器,首先验证表单本身是否被定义,否则它会抛出一个错误,说表单未定义,因为首先它会尝试 运行 在表单已构建。
// form builder
private buildForm(): void {
this.changePasswordForm = this.fb.group({
currentPass: ['', Validators.required],
newPass: ['', Validators.required],
confirmPass: ['', [Validators.required, this.passwordMatcher.bind(this)]],
});
}
// confirm new password validator
private passwordMatcher(control: FormControl): { [s: string]: boolean } {
if (
this.changePasswordForm &&
(control.value !== this.changePasswordForm.controls.newPass.value)
) {
return { passwordNotMatch: true };
}
return null;
}
它只是检查新密码字段与确认密码字段的值是否相同。是特定于 确认密码 字段而不是整个表单的验证器。
您只需验证 this.changePasswordForm
是否已定义,否则在构建表单时会抛出未定义的错误。
它工作得很好,没有创建指令或错误状态匹配器。
无需使用嵌套表单组和自定义 ErrorStateMatcher 来确认密码验证。添加这些步骤是为了促进密码字段之间的协调,但您可以在没有所有开销的情况下做到这一点。
这是一个例子:
this.registrationForm = this.fb.group({
username: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
password1: ['', [Validators.required, (control) => this.validatePasswords(control, 'password1') ] ],
password2: ['', [Validators.required, (control) => this.validatePasswords(control, 'password2') ] ]
});
请注意,我们将额外的上下文传递给 validatePasswords 方法(无论源是 password1 还是 password2)。
validatePasswords(control: AbstractControl, name: string) {
if (this.registrationForm === undefined || this.password1.value === '' || this.password2.value === '') {
return null;
} else if (this.password1.value === this.password2.value) {
if (name === 'password1' && this.password2.hasError('passwordMismatch')) {
this.password1.setErrors(null);
this.password2.updateValueAndValidity();
} else if (name === 'password2' && this.password1.hasError('passwordMismatch')) {
this.password2.setErrors(null);
this.password1.updateValueAndValidity();
}
return null;
} else {
return {'passwordMismatch': { value: 'The provided passwords do not match'}};
}
请注意,当密码匹配时,我们会与其他密码字段协调以更新其验证。这将清除任何陈旧的密码不匹配错误。
为了完整起见,这里是定义 this.password1
和 this.password2
的 getter。
get password1(): AbstractControl {
return this.registrationForm.get('password1');
}
get password2(): AbstractControl {
return this.registrationForm.get('password2');
}
反应形式的单一方法
类型说明
// All is this method
onPasswordChange() {
if (this.confirm_password.value == this.password.value) {
this.confirm_password.setErrors(null);
} else {
this.confirm_password.setErrors({ mismatch: true });
}
}
// getting the form control elements
get password(): AbstractControl {
return this.form.controls['password'];
}
get confirm_password(): AbstractControl {
return this.form.controls['confirm_password'];
}
HTML
// PASSWORD FIELD
<input type="password" formControlName="password" (change)="onPasswordChange()"/>
// CONFIRM PASSWORD FIELD
<input type="password" formControlName="confirm_password" (change)="onPasswordChange()" />
// SHOW ERROR IF MISMATCH
<span *ngIf="confirm_password.hasError('mismatch')">Password do not match.</span>
您可以使用这种方式来满足这个要求。我使用以下方法来验证密码和确认密码。
要使用此方法,您必须从 @angular/forms
库导入 FormGroup
。
import { FormBuilder, Validators, FormGroup } from '@angular/forms';
FormBuilder 组:
this.myForm= this.formBuilder.group({
password : ['', Validators.compose([Validators.required])],
confirmPassword : ['', Validators.compose([Validators.required])],
},
{validator: this.checkPassword('password', 'confirmPassword') }
);
验证两个字段的方法:
checkPassword(controlName: string, matchingControlName: string) {
return (formGroup: FormGroup) => {
const control = formGroup.controls[controlName];
const matchingControl = formGroup.controls[matchingControlName];
if (matchingControl.errors && !matchingControl.errors.mustMatch) {
// return if another validator has already found an error on the matchingControl
return;
}
// set error on matchingControl if validation fails
if (control.value !== matchingControl.value) {
matchingControl.setErrors({ mustMatch: true });
this.isPasswordSame = (matchingControl.status == 'VALID') ? true : false;
} else {
matchingControl.setErrors(null);
this.isPasswordSame = (matchingControl.status == 'VALID') ? true : false;
}
}
}
HTML:
我在这里使用个性化的 isPasswordSame 变量,您可以使用内置的 hasError 或任何其他变量。
<form [formGroup]="myForm">
<ion-item>
<ion-label position="floating">Password</ion-label>
<ion-input required type="text" formControlName="password" placeholder="Enter Password"></ion-input>
</ion-item>
<ion-label *ngIf="myForm.controls.password.valid">
<p class="error">Please enter password!!</p>
</ion-label>
<ion-item>
<ion-label position="floating">Confirm Password</ion-label>
<ion-input required type="text" formControlName="confirmPassword" placeholder="Enter Confirm Password"></ion-input>
</ion-item>
<ion-label *ngIf="isPasswordSame">
<p class="error">Password and Confrim Password must be same!!</p>
</ion-label>
</form>
我想使用material执行密码和确认密码验证仅限组件,如果 confirm password field doesn't match
和 if it is empty
, 确认密码 字段下方会显示一条错误消息。尝试了很多资源都无法实现。
也试过this video。
这是我正在寻找的 material 组件
HTML
<mat-form-field >
<input matInput placeholder="New password" [type]="hide ? 'password'
: 'text'" [formControl]="passFormControl" required>
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' :
'visibility_off'}}</mat-icon>
<mat-error *ngIf="passFormControl.hasError('required')">
Please enter your newpassword
</mat-error>
</mat-form-field>
<mat-form-field >
<input matInput placeholder="Confirm password" [type]="hide ?
'password' : 'text'" [formControl]="confirmFormControl"
required>
<mat-icon matSuffix (click)="hide = !hide">{{hide ? 'visibility' :
'visibility_off'}}</mat-icon>
<mat-error *ngIf="confirmFormControl.hasError('required')">
Confirm your password
</mat-error>
</mat-form-field>
TS
import {Component, OnInit } from '@angular/core';
import {FormControl, FormGroupDirective, NgForm, Validators} from
'@angular/forms';
import {ErrorStateMatcher} from '@angular/material/core';
@Component({
selector: 'asd-set-pass',
templateUrl: './set-pass.component.html',
styleUrls: ['./set-pass.component.css']
})
passFormControl = new FormControl('', [
Validators.required,
]);
confirmFormControl = new FormControl('', [
Validators.required,
]);
hide =true;
}
它正在验证以下条件 1) 如果密码和确认密码字段为空,则显示错误文本。
我想与 (.ts) 文件中的字段进行比较,例如它如何验证空字段,以及如果确认密码字段为空则出现错误。
这个问题可以结合这两个答案来解决:
所以首先,您需要一个自定义验证程序来检查密码,它可能如下所示:
checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => {
let pass = group.get('password').value;
let confirmPass = group.get('confirmPassword').value
return pass === confirmPass ? null : { notSame: true }
}
并且您将为您的字段创建一个表单组,而不仅仅是两个表单控件,然后为您的表单组标记该自定义验证器:
this.myForm = this.fb.group({
password: ['', [Validators.required]],
confirmPassword: ['']
}, { validators: this.checkPasswords })
然后如其他答案中所述,mat-error
仅在 FormControl 无效时显示,因此您需要一个错误状态匹配器:
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const invalidCtrl = !!(control?.invalid && control?.parent?.dirty);
const invalidParent = !!(control?.parent?.invalid && control?.parent?.dirty);
return invalidCtrl || invalidParent;
}
}
在上面你可以调整何时显示错误信息。我只会在触摸 password
字段时显示消息。我也想在上面从 confirmPassword
字段中删除 required
验证器,因为如果密码不匹配,表单无论如何都无效。
然后在组件中,新建一个ErrorStateMatcher
:
matcher = new MyErrorStateMatcher();
最后,模板将如下所示:
<form [formGroup]="myForm">
<mat-form-field>
<input matInput placeholder="New password" formControlName="password" required>
<mat-error *ngIf="myForm.hasError('required', 'password')">
Please enter your new password
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Confirm password" formControlName="confirmPassword" [errorStateMatcher]="matcher">
<mat-error *ngIf="myForm.hasError('notSame')">
Passwords do not match
</mat-error>
</mat-form-field>
</form>
下面是使用上述代码的演示:StackBlitz
如果您不仅有密码和验证密码字段。 像这样,确认密码字段只会在用户在此字段上输入内容时突出显示错误:
validators.ts
import { FormGroup, FormControl, Validators, FormBuilder, FormGroupDirective, NgForm } from '@angular/forms';
import { ErrorStateMatcher } from '@angular/material/core';
export const EmailValidation = [Validators.required, Validators.email];
export const PasswordValidation = [
Validators.required,
Validators.minLength(6),
Validators.maxLength(24),
];
export class RepeatPasswordEStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
return (control && control.parent.get('password').value !== control.parent.get('passwordAgain').value && control.dirty)
}
}
export function RepeatPasswordValidator(group: FormGroup) {
const password = group.controls.password.value;
const passwordConfirmation = group.controls.passwordAgain.value;
return password === passwordConfirmation ? null : { passwordsNotEqual: true }
}
register.component.ts
import { FormGroup, FormControl, Validators, FormBuilder} from '@angular/forms';
import { EmailValidation, PasswordValidation, RepeatPasswordEStateMatcher, RepeatPasswordValidator } from 'validators';
...
form: any;
passwordsMatcher = new RepeatPasswordEStateMatcher;
constructor(private formBuilder: FormBuilder) {
this.form = this.formBuilder.group ( {
email: new FormControl('', EmailValidation),
password: new FormControl('', PasswordValidation),
passwordAgain: new FormControl(''),
acceptTerms: new FormControl('', [Validators.requiredTrue])
}, { validator: RepeatPasswordValidator });
}
...
register.component.html
<form [formGroup]="form" (ngSubmit)="submitAccount(form)">
<div class="form-content">
<div class="form-field">
<mat-form-field>
<input matInput formControlName="email" placeholder="Email">
<mat-error *ngIf="form.get('email').hasError('required')">
E-mail is mandatory.
</mat-error>
<mat-error *ngIf="form.get('email').hasError('email')">
Incorrect E-mail.
</mat-error>
</mat-form-field>
</div>
<div class="form-field">
<mat-form-field>
<input matInput formControlName="password" placeholder="Password" type="password">
<mat-hint class="ac-form-field-description">Between 6 and 24 characters.</mat-hint>
<mat-error *ngIf="form.get('password').hasError('required')">
Password is mandatory.
</mat-error>
<mat-error *ngIf="form.get('password').hasError('minlength')">
Password with less than 6 characters.
</mat-error>
<mat-error *ngIf="form.get('password').hasError('maxlength')">
Password with more than 24 characters.
</mat-error>
</mat-form-field>
</div>
<div class="form-field">
<mat-form-field>
<input matInput formControlName="passwordAgain" placeholder="Confirm the password" type="password" [errorStateMatcher]="passwordsMatcher">
<mat-error *ngIf="form.hasError('passwordsNotEqual')" >Passwords are different. They should be equal!</mat-error>
</mat-form-field>
</div>
<div class="form-field">
<mat-checkbox name="acceptTerms" formControlName="acceptTerms">I accept terms and conditions</mat-checkbox>
</div>
</div>
<div class="form-bottom">
<button mat-raised-button [disabled]="!form.valid">Create Account</button>
</div>
</form>
希望对您有所帮助!
我正在使用 angular 6,我一直在寻找匹配密码和确认密码的最佳方法。这也可用于匹配表单中的任意两个输入。我使用了 Angular 指令。我一直想用它们
ng g d compare-validators --spec false and i will be added in your module. Below is the directive
import { Directive, Input } from '@angular/core';
import { Validator, NG_VALIDATORS, AbstractControl, ValidationErrors } from '@angular/forms';
import { Subscription } from 'rxjs';
@Directive({
// tslint:disable-next-line:directive-selector
selector: '[compare]',
providers: [{ provide: NG_VALIDATORS, useExisting: CompareValidatorDirective, multi: true}]
})
export class CompareValidatorDirective implements Validator {
// tslint:disable-next-line:no-input-rename
@Input('compare') controlNameToCompare;
validate(c: AbstractControl): ValidationErrors | null {
if (c.value.length < 6 || c.value === null) {
return null;
}
const controlToCompare = c.root.get(this.controlNameToCompare);
if (controlToCompare) {
const subscription: Subscription = controlToCompare.valueChanges.subscribe(() => {
c.updateValueAndValidity();
subscription.unsubscribe();
});
}
return controlToCompare && controlToCompare.value !== c.value ? {'compare': true } : null;
}
}
现在在你的组件中
<div class="col-md-6">
<div class="form-group">
<label class="bmd-label-floating">Password</label>
<input type="password" class="form-control" formControlName="usrpass" [ngClass]="{ 'is-invalid': submitAttempt && f.usrpass.errors }">
<div *ngIf="submitAttempt && signupForm.controls['usrpass'].errors" class="invalid-feedback">
<div *ngIf="signupForm.controls['usrpass'].errors.required">Your password is required</div>
<div *ngIf="signupForm.controls['usrpass'].errors.minlength">Password must be at least 6 characters</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="bmd-label-floating">Confirm Password</label>
<input type="password" class="form-control" formControlName="confirmpass" compare = "usrpass"
[ngClass]="{ 'is-invalid': submitAttempt && f.confirmpass.errors }">
<div *ngIf="submitAttempt && signupForm.controls['confirmpass'].errors" class="invalid-feedback">
<div *ngIf="signupForm.controls['confirmpass'].errors.required">Your confirm password is required</div>
<div *ngIf="signupForm.controls['confirmpass'].errors.minlength">Password must be at least 6 characters</div>
<div *ngIf="signupForm.controls['confirmpass'].errors['compare']">Confirm password and Password dont match</div>
</div>
</div>
</div>
希望这篇文章能帮到你
*此解决方案适用于反应式
您可能听说过确认密码被称为跨域验证。而我们平时写的字段级验证器只能应用于单个字段。对于跨文件验证,您可能必须编写一些父级验证器。对于具体的确认密码的情况,我宁愿这样做:
this.form.valueChanges.subscribe(field => {
if (field.password !== field.confirm) {
this.confirm.setErrors({ mismatch: true });
} else {
this.confirm.setErrors(null);
}
});
这是模板:
<mat-form-field>
<input matInput type="password" placeholder="Password" formControlName="password">
<mat-error *ngIf="password.hasError('required')">Required</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput type="password" placeholder="Confirm New Password" formControlName="confirm">`enter code here`
<mat-error *ngIf="confirm.hasError('mismatch')">Password does not match the confirm password</mat-error>
</mat-form-field>
我在 AJT_82 的回答中发现了一个错误。由于我没有足够的声誉在 AJT_82 的回答下发表评论,我必须 post 这个答案中的错误和解决方案。
这是错误:
解决方法:在下面的代码中:
export class MyErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const invalidCtrl = !!(control && control.invalid && control.parent.dirty);
const invalidParent = !!(control && control.parent && control.parent.invalid && control.parent.dirty);
return (invalidCtrl || invalidParent);
}
}
将control.parent.invalid
更改为control.parent.hasError('notSame')
将解决此问题。
经过小改动,问题解决。
编辑:要仅在用户开始输入后验证“确认密码”字段,您可以 return 改为
return ((invalidCtrl || invalidParent) && control.valid);
我的回答很简单>我在 angular 6
中使用模板驱动创建了密码并确认了密码验证我的 html 文件
<div class="form-group">
<label class="label-sm">Confirm Password</label>
<input class="form-control" placeholder="Enter Password" type="password" #confirm_password="ngModel" [(ngModel)]="userModel.confirm_password" name="confirm_password" required (keyup)="checkPassword($event)" />
<div *ngIf="confirm_password.errors && (confirm_password.dirty||confirm_password.touched||signup.submitted)">
<div class="error" *ngIf="confirm_password.errors.required">Please confirm your password</div>
</div>
<div *ngIf="i" class='error'>Password does not match</div>
</div>
我的打字稿文件
public i: boolean;
checkPassword(event) {
const password = this.userModel.password;
const confirm_new_password = event.target.value;
if (password !== undefined) {
if (confirm_new_password !== password) {
this.i = true;
} else {
this.i = false;
}
}
}
当点击提交按钮时,我检查我的值是真还是假
如果为真
if (this.i) {
return false;
}
else{
**form submitted code comes here**
}
您可以简单地使用密码字段值作为确认密码字段的模式。
例如:
<div class="form-group">
<input type="password" [(ngModel)]="userdata.password" name="password" placeholder="Password" class="form-control"
required #password="ngModel" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}" />
<div *ngIf="password.invalid && (myform.submitted || password.touched)" class="alert alert-danger">
<div *ngIf="password.errors.required"> Password is required. </div>
<div *ngIf="password.errors.pattern"> Must contain at least one number and one uppercase and lowercase letter,
and at least 8 or more characters.</div>
</div>
</div>
<div class="form-group">
<input type="password" [(ngModel)]="userdata.confirmpassword" name="confirmpassword" placeholder="Confirm Password"
class="form-control" required #confirmpassword="ngModel" pattern="{{ password.value }}" />
<div *ngIf=" confirmpassword.invalid && (myform.submitted || confirmpassword.touched)" class="alert alert-danger">
<div *ngIf="confirmpassword.errors.required"> Confirm password is required. </div>
<div *ngIf="confirmpassword.errors.pattern"> Password & Confirm Password does not match.</div>
</div>
</div>
我是这样做的。希望对您有所帮助。
HTML :
<form [formGroup]='addAdminForm'>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Password</label>
<div class="col-sm-7">
<input type="password" class="form-control" formControlName='password' (keyup)="checkPassSame()">
<div *ngIf="addAdminForm.controls?.password?.invalid && addAdminForm.controls?.password.touched">
<p *ngIf="addAdminForm.controls?.password?.errors.required" class="errorMsg">*This field is required.</p>
</div>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">Confirm Password</label>
<div class="col-sm-7">
<input type="password" class="form-control" formControlName='confPass' (keyup)="checkPassSame()">
<div *ngIf="addAdminForm.controls?.confPass?.invalid && addAdminForm.controls?.confPass.touched">
<p *ngIf="addAdminForm.controls?.confPass?.errors.required" class="errorMsg">*This field is required.</p>
</div>
<div *ngIf="passmsg != '' && !addAdminForm.controls?.confPass?.errors?.required">
<p class="errorMsg">*{{passmsg}}</p>
</div>
</div>
</div>
</form>
TS 文件:
export class AddAdminAccountsComponent implements OnInit {
addAdminForm: FormGroup;
password: FormControl;
confPass: FormControl;
passmsg: string;
constructor(
private http: HttpClient,
private router: Router,
) {
}
ngOnInit() {
this.createFormGroup();
}
// |---------------------------------------------------------------------------------------
// |------------------------ form initialization -------------------------
// |---------------------------------------------------------------------------------------
createFormGroup() {
this.addAdminForm = new FormGroup({
password: new FormControl('', [Validators.required]),
confPass: new FormControl('', [Validators.required]),
})
}
// |---------------------------------------------------------------------------------------
// |------------------------ Check method for password and conf password same or not -------------------------
// |---------------------------------------------------------------------------------------
checkPassSame() {
let pass = this.addAdminForm.value.password;
let passConf = this.addAdminForm.value.confPass;
if(pass == passConf && this.addAdminForm.valid === true) {
this.passmsg = "";
return false;
}else {
this.passmsg = "Password did not match.";
return true;
}
}
}
我最简单的方法:
(它也可以与电子邮件一起使用,例如)
public static matchValues(
matchTo: string // name of the control to match to
): (AbstractControl) => ValidationErrors | null {
return (control: AbstractControl): ValidationErrors | null => {
return !!control.parent &&
!!control.parent.value &&
control.value === control.parent.controls[matchTo].value
? null
: { isMatching: false };
};
}
在您的组件中:
this.SignUpForm = this.formBuilder.group({
password: [undefined, [Validators.required]],
passwordConfirm: [undefined,
[
Validators.required,
matchValues('password'),
],
],
});
跟进:
正如其他人在评论中指出的那样,如果您通过修复 password
字段来修复错误,错误不会消失,因为验证会在 passwordConfirm
输入上触发。这可以通过多种方式解决。我认为最好的是:
this.SignUpForm .controls.password.valueChanges.subscribe(() => {
this.SignUpForm .controls.confirmPassword.updateValueAndValidity();
});
关于 password
改变,revliadte confirmPassword
。
只要做一个标准的自定义验证器,首先验证表单本身是否被定义,否则它会抛出一个错误,说表单未定义,因为首先它会尝试 运行 在表单已构建。
// form builder
private buildForm(): void {
this.changePasswordForm = this.fb.group({
currentPass: ['', Validators.required],
newPass: ['', Validators.required],
confirmPass: ['', [Validators.required, this.passwordMatcher.bind(this)]],
});
}
// confirm new password validator
private passwordMatcher(control: FormControl): { [s: string]: boolean } {
if (
this.changePasswordForm &&
(control.value !== this.changePasswordForm.controls.newPass.value)
) {
return { passwordNotMatch: true };
}
return null;
}
它只是检查新密码字段与确认密码字段的值是否相同。是特定于 确认密码 字段而不是整个表单的验证器。
您只需验证 this.changePasswordForm
是否已定义,否则在构建表单时会抛出未定义的错误。
它工作得很好,没有创建指令或错误状态匹配器。
无需使用嵌套表单组和自定义 ErrorStateMatcher 来确认密码验证。添加这些步骤是为了促进密码字段之间的协调,但您可以在没有所有开销的情况下做到这一点。
这是一个例子:
this.registrationForm = this.fb.group({
username: ['', Validators.required],
email: ['', [Validators.required, Validators.email]],
password1: ['', [Validators.required, (control) => this.validatePasswords(control, 'password1') ] ],
password2: ['', [Validators.required, (control) => this.validatePasswords(control, 'password2') ] ]
});
请注意,我们将额外的上下文传递给 validatePasswords 方法(无论源是 password1 还是 password2)。
validatePasswords(control: AbstractControl, name: string) {
if (this.registrationForm === undefined || this.password1.value === '' || this.password2.value === '') {
return null;
} else if (this.password1.value === this.password2.value) {
if (name === 'password1' && this.password2.hasError('passwordMismatch')) {
this.password1.setErrors(null);
this.password2.updateValueAndValidity();
} else if (name === 'password2' && this.password1.hasError('passwordMismatch')) {
this.password2.setErrors(null);
this.password1.updateValueAndValidity();
}
return null;
} else {
return {'passwordMismatch': { value: 'The provided passwords do not match'}};
}
请注意,当密码匹配时,我们会与其他密码字段协调以更新其验证。这将清除任何陈旧的密码不匹配错误。
为了完整起见,这里是定义 this.password1
和 this.password2
的 getter。
get password1(): AbstractControl {
return this.registrationForm.get('password1');
}
get password2(): AbstractControl {
return this.registrationForm.get('password2');
}
反应形式的单一方法
类型说明
// All is this method
onPasswordChange() {
if (this.confirm_password.value == this.password.value) {
this.confirm_password.setErrors(null);
} else {
this.confirm_password.setErrors({ mismatch: true });
}
}
// getting the form control elements
get password(): AbstractControl {
return this.form.controls['password'];
}
get confirm_password(): AbstractControl {
return this.form.controls['confirm_password'];
}
HTML
// PASSWORD FIELD
<input type="password" formControlName="password" (change)="onPasswordChange()"/>
// CONFIRM PASSWORD FIELD
<input type="password" formControlName="confirm_password" (change)="onPasswordChange()" />
// SHOW ERROR IF MISMATCH
<span *ngIf="confirm_password.hasError('mismatch')">Password do not match.</span>
您可以使用这种方式来满足这个要求。我使用以下方法来验证密码和确认密码。
要使用此方法,您必须从 @angular/forms
库导入 FormGroup
。
import { FormBuilder, Validators, FormGroup } from '@angular/forms';
FormBuilder 组:
this.myForm= this.formBuilder.group({
password : ['', Validators.compose([Validators.required])],
confirmPassword : ['', Validators.compose([Validators.required])],
},
{validator: this.checkPassword('password', 'confirmPassword') }
);
验证两个字段的方法:
checkPassword(controlName: string, matchingControlName: string) {
return (formGroup: FormGroup) => {
const control = formGroup.controls[controlName];
const matchingControl = formGroup.controls[matchingControlName];
if (matchingControl.errors && !matchingControl.errors.mustMatch) {
// return if another validator has already found an error on the matchingControl
return;
}
// set error on matchingControl if validation fails
if (control.value !== matchingControl.value) {
matchingControl.setErrors({ mustMatch: true });
this.isPasswordSame = (matchingControl.status == 'VALID') ? true : false;
} else {
matchingControl.setErrors(null);
this.isPasswordSame = (matchingControl.status == 'VALID') ? true : false;
}
}
}
HTML: 我在这里使用个性化的 isPasswordSame 变量,您可以使用内置的 hasError 或任何其他变量。
<form [formGroup]="myForm">
<ion-item>
<ion-label position="floating">Password</ion-label>
<ion-input required type="text" formControlName="password" placeholder="Enter Password"></ion-input>
</ion-item>
<ion-label *ngIf="myForm.controls.password.valid">
<p class="error">Please enter password!!</p>
</ion-label>
<ion-item>
<ion-label position="floating">Confirm Password</ion-label>
<ion-input required type="text" formControlName="confirmPassword" placeholder="Enter Confirm Password"></ion-input>
</ion-item>
<ion-label *ngIf="isPasswordSame">
<p class="error">Password and Confrim Password must be same!!</p>
</ion-label>
</form>