代码直接跳入验证器并破坏一切
Code jumps straight into validator and breaks everything
我已经编写了自己的验证器来检查我的反应式表单的输入字段,但它们似乎不起作用。前两个永远不会产生错误,最后一个一旦我将它添加到我的代码中就会破坏一切。通过占卜,我一直在尽我所能进行调试,我发现使用我的 validatePasswords,他立即跳入该方法,而我什至没有触及任何东西。如果你们中的任何人能弄清楚为什么它会这样做或者为什么我的其他验证器永远不会产生错误,那就太棒了!
我的 3 个自定义验证器
function validateEmail(control: FormGroup): { [key: string]: any } {
var mailReg = /^([a-zA-Z]+[a-zA-Z0-9.\-_éèàùäëïöüâêîôû]*)@([a-z]+)[.]([a-z]+)([.][a-z]+)*$/g;
if (!mailReg.test(control.get('email').value)) {
return { noValidEmail: true };
}
return null;
}
function validatePhone(control: FormGroup): { [key: string]: any } {
var phoneReg = /^0{0,2}(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{7,14}$/;
if (!phoneReg.test(control.get('phone').value)) {
return { noValidPhone: true };
}
return null;
}
function validatePassword(control: FormGroup): { [key: string]: any } {
if (
control.get('password').value !== control.get('passwordConfirmation').value
) {
return { noMatchingPasswords: true };
}
return null;
}
我的构造函数和表单:
public register: FormGroup;
constructor(
public dialogRef: MatDialogRef<RegisterFormComponent>,
private fb: FormBuilder,
private http: HttpClient
) {}
ngOnInit() {
this.register = this.fb.group({
firstName: ['', [Validators.required, Validators.minLength(2)]],
lastName: ['', [Validators.required, Validators.minLength(2)]],
email: [
'',
[Validators.required, Validators.minLength(5)],
validateEmail
],
phone: [
'',
[Validators.required, Validators.minLength(8)],
validatePhone
],
country: [''],
password: ['', [Validators.required, Validators.minLength(5)]],
passwordConfirmation: [
'',
[Validators.required, Validators.minLength(5), validatePassword]
]
});
}
我的报错方法
getErrorMessage(errors: any) {
if (errors.required) {
return 'is required';
} else if (errors.noValidEmail) {
return 'not a valid email';
} else if (errors.noValidPhone) {
return 'no valid phone number';
} else if (errors.noMatchingPasswords) {
return 'passwords don\'t match';
} else if (errors.minlength) {
return `need at least ${errors.minlength.requiredLength} characters`;
}
}
它产生的错误:
ERROR TypeError: Cannot read property 'get' of undefined
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.addControl (forms.js:5280)
at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName._setUpControl (forms.js:5882)
at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName.ngOnChanges (forms.js:5803)
at checkAndUpdateDirectiveInline (core.js:22085)
at checkAndUpdateNodeInline (core.js:23353)
at checkAndUpdateNode (core.js:23315)
at debugCheckAndUpdateNode (core.js:23949)
at debugCheckDirectivesFn (core.js:23909)
at Object.eval [as updateDirectives] (RegisterFormComponent.html:5)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:23901)
最后,我在 html
中的表格
<h3 mat-dialog-title>Register</h3>
<mat-dialog-content>
<form [formGroup]="register" (ngSubmit)="onSubmit()">
<mat-form-field>
<input matInput aria-label="First name" placeholder="First name" type="text" formControlName="firstName"
class="browser-default" required />
<mat-error *ngIf="register.get('firstName')['errors'] && register.get('firstName').touched">
{{ getErrorMessage(register.get('firstName')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Last name" placeholder="Last name" type="text" formControlName="lastName"
class="browser-default" required />
<mat-error *ngIf="register.get('lastName')['errors'] && register.get('lastName').touched">
{{ getErrorMessage(register.get('lastName')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Email" placeholder="Email" type="text" formControlName="email" class="browser-default"
required />
<mat-error *ngIf="register.get('email')['errors'] && register.get('email').touched">
{{ getErrorMessage(register.get('email')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Phone" placeholder="Phone" type="text" formControlName="phone" class="browser-default"
required />
<mat-error *ngIf="register.get('phone')['errors'] && register.get('phone').touched">
{{ getErrorMessage(register.get('phone')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Country" placeholder="Country" type="text" formControlName="country"
class="browser-default" />
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Password" placeholder="Password" type="password" formControlName="password"
class="browser-default" required />
<mat-error *ngIf="register.get('password')['errors'] && register.get('password').touched">
{{ getErrorMessage(register.get('password')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Confirmation Password" placeholder="Confirmation Password" type="password"
formControlName="passwordConfirmation" class="browser-default" required />
<mat-error *ngIf="register.get('passwordConfirmation')['errors'] && register.get('passwordConfirmation').touched">
{{ getErrorMessage(register.get('passwordConfirmation')['errors']) }}
</mat-error>
</mat-form-field>
<div class="buttonDiv">
<button mat-button (click)="onNoClick()">Cancel</button>
<button mat-button type="submit" [disabled]="!register.valid">Register</button>
</div>
</form>
</mat-dialog-content>
更新:
这些错误是新的,但现在也会抛出:
ERROR Error: formGroup expects a FormGroup instance. Please pass one in.
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});
at Function.push../node_modules/@angular/forms/fesm5/forms.js.ReactiveErrors.missingFormException (forms.js:1443)
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective._checkFormPresent (forms.js:5414)
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.ngOnChanges (forms.js:5237)
at checkAndUpdateDirectiveInline (core.js:22085)
at checkAndUpdateNodeInline (core.js:23353)
at checkAndUpdateNode (core.js:23315)
at debugCheckAndUpdateNode (core.js:23949)
at debugCheckDirectivesFn (core.js:23909)
at Object.eval [as updateDirectives] (RegisterFormComponent.html:3)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:23901)
和
ERROR TypeError: Cannot read property 'value' of null
at validatePassword (register-form.component.ts:29)
at forms.js:658
at Array.map (<anonymous>)
at _executeValidators (forms.js:658)
at FormControl.validator (forms.js:623)
at FormControl.push../node_modules/@angular/forms/fesm5/forms.js.AbstractControl._runValidator (forms.js:2914)
at FormControl.push../node_modules/@angular/forms/fesm5/forms.js.AbstractControl.updateValueAndValidity (forms.js:2890)
at new FormControl (forms.js:3241)
at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder.control (forms.js:6462)
at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder._createControl (forms.js:6502)
(第29行是这样的:control.get('password').value !== control.get('passwordConfirmation').value
)
鉴于 validatePassword
自定义验证器涉及 cross-field validation(跨多个字段的验证 - FormControls password
和 passwordConfirmation
),您应该在第二个中传递该验证器register
形式的初始化参数。
您可以保持其他 FormControl 不变。从 passwordConfirmation 中删除 validatePassword
,并将其添加到 formBuilder 的第二个参数中。
this.register = this.fb.group({
.
.
password: ['', [Validators.required, Validators.minLength(5)]],
passwordConfirmation: [
'',
[Validators.required, Validators.minLength(5)]
]
}, { validators: validatePassword });
关于你的第二个问题,是因为页面渲染时register
FormGroup未定义。您应该将其移动到您的构造函数中,或者在 class.
上声明 'register' 属性 时简单地初始化 FormControls
constructor(
public dialogRef: MatDialogRef<RegisterFormComponent>,
private fb: FormBuilder,
private http: HttpClient
) {
this.register = fb.group({
.
.
// your FormControls
.
});
}
或
export class YourComponent implements OnInit {
public register: FormGroup = this.fb.group({
.
.
// your FormControls
.
})
我已经编写了自己的验证器来检查我的反应式表单的输入字段,但它们似乎不起作用。前两个永远不会产生错误,最后一个一旦我将它添加到我的代码中就会破坏一切。通过占卜,我一直在尽我所能进行调试,我发现使用我的 validatePasswords,他立即跳入该方法,而我什至没有触及任何东西。如果你们中的任何人能弄清楚为什么它会这样做或者为什么我的其他验证器永远不会产生错误,那就太棒了!
我的 3 个自定义验证器
function validateEmail(control: FormGroup): { [key: string]: any } {
var mailReg = /^([a-zA-Z]+[a-zA-Z0-9.\-_éèàùäëïöüâêîôû]*)@([a-z]+)[.]([a-z]+)([.][a-z]+)*$/g;
if (!mailReg.test(control.get('email').value)) {
return { noValidEmail: true };
}
return null;
}
function validatePhone(control: FormGroup): { [key: string]: any } {
var phoneReg = /^0{0,2}(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\d{7,14}$/;
if (!phoneReg.test(control.get('phone').value)) {
return { noValidPhone: true };
}
return null;
}
function validatePassword(control: FormGroup): { [key: string]: any } {
if (
control.get('password').value !== control.get('passwordConfirmation').value
) {
return { noMatchingPasswords: true };
}
return null;
}
我的构造函数和表单:
public register: FormGroup;
constructor(
public dialogRef: MatDialogRef<RegisterFormComponent>,
private fb: FormBuilder,
private http: HttpClient
) {}
ngOnInit() {
this.register = this.fb.group({
firstName: ['', [Validators.required, Validators.minLength(2)]],
lastName: ['', [Validators.required, Validators.minLength(2)]],
email: [
'',
[Validators.required, Validators.minLength(5)],
validateEmail
],
phone: [
'',
[Validators.required, Validators.minLength(8)],
validatePhone
],
country: [''],
password: ['', [Validators.required, Validators.minLength(5)]],
passwordConfirmation: [
'',
[Validators.required, Validators.minLength(5), validatePassword]
]
});
}
我的报错方法
getErrorMessage(errors: any) {
if (errors.required) {
return 'is required';
} else if (errors.noValidEmail) {
return 'not a valid email';
} else if (errors.noValidPhone) {
return 'no valid phone number';
} else if (errors.noMatchingPasswords) {
return 'passwords don\'t match';
} else if (errors.minlength) {
return `need at least ${errors.minlength.requiredLength} characters`;
}
}
它产生的错误:
ERROR TypeError: Cannot read property 'get' of undefined
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.addControl (forms.js:5280)
at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName._setUpControl (forms.js:5882)
at FormControlName.push../node_modules/@angular/forms/fesm5/forms.js.FormControlName.ngOnChanges (forms.js:5803)
at checkAndUpdateDirectiveInline (core.js:22085)
at checkAndUpdateNodeInline (core.js:23353)
at checkAndUpdateNode (core.js:23315)
at debugCheckAndUpdateNode (core.js:23949)
at debugCheckDirectivesFn (core.js:23909)
at Object.eval [as updateDirectives] (RegisterFormComponent.html:5)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:23901)
最后,我在 html
中的表格<h3 mat-dialog-title>Register</h3>
<mat-dialog-content>
<form [formGroup]="register" (ngSubmit)="onSubmit()">
<mat-form-field>
<input matInput aria-label="First name" placeholder="First name" type="text" formControlName="firstName"
class="browser-default" required />
<mat-error *ngIf="register.get('firstName')['errors'] && register.get('firstName').touched">
{{ getErrorMessage(register.get('firstName')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Last name" placeholder="Last name" type="text" formControlName="lastName"
class="browser-default" required />
<mat-error *ngIf="register.get('lastName')['errors'] && register.get('lastName').touched">
{{ getErrorMessage(register.get('lastName')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Email" placeholder="Email" type="text" formControlName="email" class="browser-default"
required />
<mat-error *ngIf="register.get('email')['errors'] && register.get('email').touched">
{{ getErrorMessage(register.get('email')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Phone" placeholder="Phone" type="text" formControlName="phone" class="browser-default"
required />
<mat-error *ngIf="register.get('phone')['errors'] && register.get('phone').touched">
{{ getErrorMessage(register.get('phone')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Country" placeholder="Country" type="text" formControlName="country"
class="browser-default" />
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Password" placeholder="Password" type="password" formControlName="password"
class="browser-default" required />
<mat-error *ngIf="register.get('password')['errors'] && register.get('password').touched">
{{ getErrorMessage(register.get('password')['errors']) }}
</mat-error>
</mat-form-field>
<mat-form-field>
<input matInput aria-label="Confirmation Password" placeholder="Confirmation Password" type="password"
formControlName="passwordConfirmation" class="browser-default" required />
<mat-error *ngIf="register.get('passwordConfirmation')['errors'] && register.get('passwordConfirmation').touched">
{{ getErrorMessage(register.get('passwordConfirmation')['errors']) }}
</mat-error>
</mat-form-field>
<div class="buttonDiv">
<button mat-button (click)="onNoClick()">Cancel</button>
<button mat-button type="submit" [disabled]="!register.valid">Register</button>
</div>
</form>
</mat-dialog-content>
更新:
这些错误是新的,但现在也会抛出:
ERROR Error: formGroup expects a FormGroup instance. Please pass one in.
Example:
<div [formGroup]="myGroup">
<input formControlName="firstName">
</div>
In your class:
this.myGroup = new FormGroup({
firstName: new FormControl()
});
at Function.push../node_modules/@angular/forms/fesm5/forms.js.ReactiveErrors.missingFormException (forms.js:1443)
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective._checkFormPresent (forms.js:5414)
at FormGroupDirective.push../node_modules/@angular/forms/fesm5/forms.js.FormGroupDirective.ngOnChanges (forms.js:5237)
at checkAndUpdateDirectiveInline (core.js:22085)
at checkAndUpdateNodeInline (core.js:23353)
at checkAndUpdateNode (core.js:23315)
at debugCheckAndUpdateNode (core.js:23949)
at debugCheckDirectivesFn (core.js:23909)
at Object.eval [as updateDirectives] (RegisterFormComponent.html:3)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:23901)
和
ERROR TypeError: Cannot read property 'value' of null
at validatePassword (register-form.component.ts:29)
at forms.js:658
at Array.map (<anonymous>)
at _executeValidators (forms.js:658)
at FormControl.validator (forms.js:623)
at FormControl.push../node_modules/@angular/forms/fesm5/forms.js.AbstractControl._runValidator (forms.js:2914)
at FormControl.push../node_modules/@angular/forms/fesm5/forms.js.AbstractControl.updateValueAndValidity (forms.js:2890)
at new FormControl (forms.js:3241)
at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder.control (forms.js:6462)
at FormBuilder.push../node_modules/@angular/forms/fesm5/forms.js.FormBuilder._createControl (forms.js:6502)
(第29行是这样的:control.get('password').value !== control.get('passwordConfirmation').value
)
鉴于 validatePassword
自定义验证器涉及 cross-field validation(跨多个字段的验证 - FormControls password
和 passwordConfirmation
),您应该在第二个中传递该验证器register
形式的初始化参数。
您可以保持其他 FormControl 不变。从 passwordConfirmation 中删除 validatePassword
,并将其添加到 formBuilder 的第二个参数中。
this.register = this.fb.group({
.
.
password: ['', [Validators.required, Validators.minLength(5)]],
passwordConfirmation: [
'',
[Validators.required, Validators.minLength(5)]
]
}, { validators: validatePassword });
关于你的第二个问题,是因为页面渲染时register
FormGroup未定义。您应该将其移动到您的构造函数中,或者在 class.
constructor(
public dialogRef: MatDialogRef<RegisterFormComponent>,
private fb: FormBuilder,
private http: HttpClient
) {
this.register = fb.group({
.
.
// your FormControls
.
});
}
或
export class YourComponent implements OnInit {
public register: FormGroup = this.fb.group({
.
.
// your FormControls
.
})