创建反应式密码确认表单控件?
Creating a reactive password confirmation form control?
我正在尝试创建一个 material 密码确认组件,它可以与 Angular 响应式表单一起使用。这样,可以在注册表单和重置密码表单中使用相同的组件。
I've created a self contained Stackblitz Demo here 工作正常(这是当控件独立使用而不嵌入另一种反应形式时)。密码字段有最小和最大长度验证限制,确认密码字段是必需的。
在满足所有验证约束且密码匹配之前,提交按钮将不会启用。
所以现在我希望能够在 Angular Material Reactive Forms 中使用该组件,并且 according to this article 控件必须实现 ControlValueAccessor
接口和 Validator
界面
所以我将这些添加到控件中并实现了 a demo here。
表单如下所示:
<mat-card class="PasswordFormTestCard">
<form class="RegistrationForm" [formGroup]="form" (ngSubmit)="submit()">
<mat-form-field>
<input
matInput
placeholder="username"
type="text"
formControlName="username"
/>
<mat-hint *ngIf="!username">Example Monica</mat-hint>
<mat-error>Please enter your username</mat-error>
</mat-form-field>
<fs-password-form formControlName="password"></fs-password-form>
<button mat-button type="submit" [disabled]="!form.valid">Submit</button>
</form>
</mat-card>
可以看出自定义密码表单控件是这样绑定的:
<fs-password-form formControlName="password"></fs-password-form>
这个“几乎”有效。
只要 confirmPassword
对话框中有任何字符,提交按钮就会启用。
控件上的validate
函数应该可以防止这种情况发生。我是这样实现的:
//=============================================
// Validator API Methods
//=============================================
validate(control: AbstractControl): ValidationErrors | null {
if (
this.passwordForm.valid &&
this.confirmPasswordControl.valid &&
this.passwordControl.valid
) {
console.log('BOTH THE FORM AND THE CONTROLS ARE VALID');
return null;
}
let errors: any = {};
errors = this.addControlErrors(errors, 'password');
errors = this.addControlErrors(errors, 'confirmPassword');
return errors;
}
addControlErrors(allErrors: any, controlName: string) {
const errors = { ...allErrors };
const controlErrors = this.passwordForm.controls[controlName].errors;
if (controlErrors) {
errors[controlName] = controlErrors;
}
return errors;
}
我认为在返回 null 之前检查表单和控件是否有效,如下所示:
this.passwordForm.valid &&
this.confirmPasswordControl.valid &&
this.passwordControl.valid
将确保自定义 PasswordForm
控件不会在实际有效之前指示它有效,但由于某种原因它会提前返回 null。
有人知道这是为什么吗?
你的时间有问题。当调用验证函数时,FormGroup 的有效性尚未更新。修复非常简单。在验证函数的顶部添加以下行:
this.passwordForm.updateValueAndValidity({
onlySelf: true,
emitEvent: false,
});
我认为它不会 side-effects。
我正在尝试创建一个 material 密码确认组件,它可以与 Angular 响应式表单一起使用。这样,可以在注册表单和重置密码表单中使用相同的组件。
I've created a self contained Stackblitz Demo here 工作正常(这是当控件独立使用而不嵌入另一种反应形式时)。密码字段有最小和最大长度验证限制,确认密码字段是必需的。
在满足所有验证约束且密码匹配之前,提交按钮将不会启用。
所以现在我希望能够在 Angular Material Reactive Forms 中使用该组件,并且 according to this article 控件必须实现 ControlValueAccessor
接口和 Validator
界面
所以我将这些添加到控件中并实现了 a demo here。
表单如下所示:
<mat-card class="PasswordFormTestCard">
<form class="RegistrationForm" [formGroup]="form" (ngSubmit)="submit()">
<mat-form-field>
<input
matInput
placeholder="username"
type="text"
formControlName="username"
/>
<mat-hint *ngIf="!username">Example Monica</mat-hint>
<mat-error>Please enter your username</mat-error>
</mat-form-field>
<fs-password-form formControlName="password"></fs-password-form>
<button mat-button type="submit" [disabled]="!form.valid">Submit</button>
</form>
</mat-card>
可以看出自定义密码表单控件是这样绑定的:
<fs-password-form formControlName="password"></fs-password-form>
这个“几乎”有效。
只要 confirmPassword
对话框中有任何字符,提交按钮就会启用。
控件上的validate
函数应该可以防止这种情况发生。我是这样实现的:
//=============================================
// Validator API Methods
//=============================================
validate(control: AbstractControl): ValidationErrors | null {
if (
this.passwordForm.valid &&
this.confirmPasswordControl.valid &&
this.passwordControl.valid
) {
console.log('BOTH THE FORM AND THE CONTROLS ARE VALID');
return null;
}
let errors: any = {};
errors = this.addControlErrors(errors, 'password');
errors = this.addControlErrors(errors, 'confirmPassword');
return errors;
}
addControlErrors(allErrors: any, controlName: string) {
const errors = { ...allErrors };
const controlErrors = this.passwordForm.controls[controlName].errors;
if (controlErrors) {
errors[controlName] = controlErrors;
}
return errors;
}
我认为在返回 null 之前检查表单和控件是否有效,如下所示:
this.passwordForm.valid &&
this.confirmPasswordControl.valid &&
this.passwordControl.valid
将确保自定义 PasswordForm
控件不会在实际有效之前指示它有效,但由于某种原因它会提前返回 null。
有人知道这是为什么吗?
你的时间有问题。当调用验证函数时,FormGroup 的有效性尚未更新。修复非常简单。在验证函数的顶部添加以下行:
this.passwordForm.updateValueAndValidity({
onlySelf: true,
emitEvent: false,
});
我认为它不会 side-effects。