问题描述
HTML 密码和确认密码表单字段集:
<mat-form-field>
<mat-label>{{ 'PAGES.LOGIN.PASSWORD' | translate }}</mat-label>
<input #registerPasswordField matInput title=" " [type]="hide ? 'password' : 'text'" [formControl]="password" required (keyup.enter)="registerConfirmField.focus()">
<button mat-icon-button matSuffix (click)="hide = !hide" [attr.aria-label]="'Hide password'" [attr.aria-pressed]="hide">
<mat-icon>{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
</button>
<mat-error *ngIf="password.invalid && password.errors?.pattern">{{ 'PAGES.REGISTER.PASSWORD_INVALID' | translate }}</mat-error>
<mat-error *ngIf="password.invalid && !password.errors?.pattern">{{ 'PAGES.LOGIN.PASSWORD_required' | translate }}</mat-error>
</mat-form-field>
<mat-form-field>
<mat-label>{{ 'PAGES.REGISTER.CONFIRM' | translate }}</mat-label>
<input #registerConfirmField matInput title=" " [type]="hide ? 'password' : 'text'" [formControl]="confirmPassword" required (keyup.enter)="loginButton.focus(); register()">
<button mat-icon-button matSuffix (click)="hide = !hide" [attr.aria-label]="'Hide password'" [attr.aria-pressed]="hide">
<mat-icon>{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
</button>
<mat-error *ngIf="confirmPassword.errors?.pattern">{{ 'PAGES.REGISTER.CONFIRM_MISMATCH' | translate }}</mat-error>
<mat-error *ngIf="confirmPassword.invalid">{{ 'PAGES.REGISTER.CONFIRM_required' | translate }}</mat-error>
</mat-form-field>
使用以下 TS 端表单字段声明:
password = new FormControl("",[
Validators.required,Validators.pattern("^((?=\\S*?[A-Z])(?=\\S*?[a-z])(?=\\S*?[0-9]).{8,255})\\S$")
])
confirmPassword = new FormControl("",confirmEquals(this,this.password) //pseudocode,obvIoUsly this won't work
])
我正在尝试为此做一些事情,我只是检查 password.value 和 confirmPassword.value 之间的相等。
我无法用 Validators.pattern() 做到这一点(我不明白为什么 Validators.pattern(this.password.value) 不起作用。文档说它也接受一个字符串在这种情况下,它在前面附加 ^ 并在后面附加 $,基本上它只对那个字符串进行正则表达式。它应该工作。但这个验证器永远不会被触发)
我已经看到大量有关密码确认问题的 stackoverflow 问题,但对我来说没有一个看起来干净或简洁(但最重要的是最新的)。
我发现了这个旧的弃用代码示例:
ngOnInit() {
this.registerForm = this.formBuilder.group({
firstName: ['',Validators.required],lastName: ['',email: ['',[Validators.required,Validators.email]],password: ['',Validators.minLength(6)]],confirmPassword: ['',Validators.required]
},{
validator: MustMatch('password','confirmPassword')
});
}
这表明 angular 在某一时刻确实费心去实现一个函数来达到这种效果。
但据我所知它还没有转移到新的 AbstractControl CLASS
字段“验证器”存在于 FormGroup 的新语法中,但我更喜欢较新的语法,在这种语法中,您不声明整个表单,而只声明每个字段,如新的 angular-material 文档中所示。
现在似乎不鼓励使用 FormBuilder。
并且我希望我的方法是 KISS 和高性能的,并且在句法上简洁。
是否有可能进行密码确认(以干净、现代的方式)而无需在公共 formGroup 下管理两个 formControl?
我会接受这是一种糟糕的方法,但我想知道为什么以及“Angular 11”的做法是什么(答案需要跟上当前的最佳实践)。
编辑:我一直在读这个:Reference - Password Validation
以及对此的评论:https://stackoverflow.com/a/12806002/4770754
不过,我必须创建自己的注册。
解决方法
使用 custom validator
你可以做到。尝试如下,
app.component.ts
password = new FormControl("",[
Validators.required,Validators.pattern(
"^((?=\\S*?[A-Z])(?=\\S*?[a-z])(?=\\S*?[0-9]).{8,255})\\S$"
)
]);
confirmPassword = new FormControl("",this.confirmEquals()
]);
confirmEquals(): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } | null =>
control.value?.toLowerCase() === this.passwordValue.toLowerCase()
? null : {noMatch: true};
}
get passwordValue() {
return this.password.value;
}
app.component.html
<mat-form-field class="example-full-width">
<input matInput placeholder="Password" [formControl]="password"/>
<mat-error *ngIf="password.dirty && password.errors?.pattern">
<strong>Pattern Wrong</strong>
</mat-error>
</mat-form-field>
<mat-form-field class="example-full-width">
<input matInput placeholder="Confirm Password" [formControl]="confirmPassword"/>
<mat-error *ngIf="confirmPassword.dirty && confirmPassword.errors?.noMatch">
<strong>Password</strong> and <strong>Confirm Password</strong> must be same
</mat-error>
</mat-form-field>
stackblitz 工作示例:https://stackblitz.com/edit/angular-ztqtaz?file=src/app/app.component.html