我在使用Angular (v4.3.6)的模型驱动表单上显示验证错误时遇到了一些问题。
在我的模型中,我有以下内容:
this.registerForm = formBuilder.group({
'email':[null,Validators.compose([Validators.required, ValidateEmail])],
'firstName':[null, Validators.required],
'lastName':[null, Validators.required],
'passwordGroup': formBuilder.group({
'password':[null, Validators.compose([Validators.required,Validators.minLength(8)])],
'passwordConfirmation':[null, Validators.required],
},{validator: ValidatePasswordConfirmation})
});引用的ValidatePasswordConfirmation自定义验证器如下所示:
export function ValidatePasswordConfirmation(group: FormGroup) {
if(group.value.password !== group.value.passwordConfirmation){
return { 'no-match':true };
}
return null;
}最后,在我的模板中,我有以下内容:
<md-form-field>
<input mdInput name="passwordConfirmation" placeholder="Confirm password" [formControl]="registerForm.controls['passwordGroup'].controls['passwordConfirmation']" [(ngModel)]="model.passwordConfirmation" type="password">
<md-error *ngIf="registerForm.controls['passwordGroup'].controls['passwordConfirmation'].hasError('required')">
Password confirmation is required
</md-error>
<md-error *ngIf="registerForm.controls['passwordGroup'].hasError('no-match')">
Passwords don't match
</md-error>
</md-form-field>但是,由'no-match‘错误控制的md-error永远不会出现。因此,为了在页面上调试它,我添加了以下内容:
no-match = {{registerForm.controls['passwordGroup'].hasError('no-match')}}
invalid = {{registerForm.controls['passwordGroup'].invalid}}如您所料,debug行显示true/false,这并不奇怪。但是,'md-error‘永远不会显示...除非显示'required‘错误。我有一种感觉,这个问题是由于formControl引用了passwordConfirmation FormControl,所以如果不是无效的,就不会显示md-FormControl。但是,我希望在外部FormGroup无效时显示此错误。
任何关于我在哪里出错的建议都会很有帮助!
最后,我尝试了其他一些方法来解决这个问题,比如在PasswordConfirmation FormControl上设置错误,这是可行的,但我想知道为什么我当前的实现失败了。
发布于 2017-11-14 20:15:43
我发现我能够使用自定义的ErrorStateMatcher解决完全相同的问题(默认的any要求控件在显示任何错误之前处于无效状态)
export class ParentErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = !!(form && form.submitted);
const controlTouched = !!(control && (control.dirty || control.touched));
const controlInvalid = !!(control && control.invalid);
const parentInvalid = !!(control && control.parent && control.parent.invalid && (control.parent.dirty || control.parent.touched));
return isSubmitted || (controlTouched && (controlInvalid || parentInvalid));
}
}这在我的页面组件中被公开为一个变量,如下所示...
@Component({
templateUrl: 'register.page.component.html',
styleUrls: ['register.page.styles.css']
})
export class RegisterPageComponent implements OnInit {
registerForm: FormGroup;
parentErrorStateMatcher = new ParentErrorStateMatcher();
// Accessors
get name() { return this.registerForm.get('name'); }
get email() { return this.registerForm.get('email'); }
get passwords() { return this.registerForm.get('passwords'); }
get password() { return this.registerForm.get('passwords.password'); }
get confirmPassword() { return this.registerForm.get('passwords.confirmPassword'); }
...用这个表格..。
this.registerForm = this.formBuilder.group({
name: ['', [
Validators.required,
Validators.maxLength(256)]
],
email: ['', [
Validators.email,
Validators.required,
Validators.maxLength(256)]
],
passwords: this.formBuilder.group({
password: ['', [
Validators.required,
Validators.maxLength(128)
]],
confirmPassword: ['', [
Validators.required
]]
},
{
validator: CustomValidators.doNotMatch('password', 'confirmPassword')
}),
});密码字段的标记(参见confirmPassword输入控件的errorStateMatcher和最后一个mat-error )...
<div formGroupName="passwords">
<mat-form-field class="full-width">
<input matInput placeholder="Password" type="password" name="password" id="password" formControlName="password" required/>
<mat-error *ngIf="password.errors && password.errors.required">
Please enter your password
</mat-error>
<mat-error *ngIf="password.errors && password.errors.maxLength">
Password must be less than 128 characters long
</mat-error>
</mat-form-field>
<mat-form-field class="full-width">
<input matInput placeholder="Confirm Password" type="password" name="confirmPassword" id="confirmPassword" formControlName="confirmPassword" required
[errorStateMatcher]="parentErrorStateMatcher"/>
<mat-error *ngIf="confirmPassword.errors && confirmPassword.errors.required">
Please confirm your password
</mat-error>
<mat-error *ngIf="passwords.errors && passwords.errors.doNotMatch">
Passwords do not match
</mat-error>
</mat-form-field>
</div>感觉比我不使用材料的时候更令人困惑,但我很高兴这种权衡,实际上唯一额外的代码是自定义匹配器:)
发布于 2017-09-21 05:51:24
我已经在像},{validator: ValidatePasswordConfirmation}这样的角度材料输入的自定义验证中遇到了这个问题,似乎这是材料的问题。这是我在Angular Material页面上的问题:https://github.com/angular/material2/issues/7084。它没有答案,所以这个问题仍然在发生。我的决定是在提交表单后使用验证,它不是非常漂亮和正确,但它是有效的。希望这个问题能在下一个版本中得到解决。
或者,如果你想要一个实时的验证,你可以这样做:
checkArePasswordsValid() {
this.passwordsAreEqual = this.passwordValue === this.passwordConfirmationValue ? true : false;
}并使用此布尔值进行验证。
发布于 2017-09-22 14:44:55
这段代码在我的例子中运行得很好。代码结构如下:
// component.ts
import { FormBuilder, FormGroup, FormControl, Validators } from '@angular/forms';
function validate(v: FormGroup): any {
let a = k.get('a');
let b = k.get('b');
if (a.value != undefined && (b.value == undefined || a.value == "none" || b.value == " ")) {
return { ab: true };
}
return null;
}
@Component({
})
export class component implements OnInit, OnDestroy {
constructor(){}
ngOnInit() {
this.registerForm = formBuilder.group({
'email':[null,Validators.compose([Validators.required, ValidateEmail])],
'firstName':[null, Validators.required],
'lastName':[null, Validators.required],
'passwordGroup': formBuilder.group({
'password':[null, Validators.compose([Validators.required,Validators.minLength(8)])],
'passwordConfirmation':[null, Validators.required],
},{validator: ValidatePasswordConfirmation})
});
}
}HTML错误消息显示if条件,其使用方式与上面在代码中提到的方式相同。
https://stackoverflow.com/questions/46330287
复制相似问题