我的反应式表单根本不起作用,所有验证都失败了。任何验证都不会出现在屏幕上,并且单击“保存”按钮时会在我的 devTools 控制台中出现以下错误:
user-register.component.html:8 ERROR TypeError: Cannot read properties of null (reading '_syncPendingControls')
at syncPendingControls (forms.mjs:3352:8)
at _FormGroupDirective.onSubmit (forms.mjs:5344:5)
at FormGroupDirective_submit_HostBindingHandler (forms.mjs:5446:24)
at executeListenerWithErrorHandling (core.mjs:24700:16)
at wrapListenerIn_markDirtyAndPreventDefault (core.mjs:24733:22)
at HTMLFormElement.<anonymous> (platform-browser.mjs:751:112)
at _ZoneDelegate.invokeTask (zone.js:402:31)
at core.mjs:14455:55
at AsyncStackTaggingZoneSpec.onInvokeTask (core.mjs:14455:36)
at _ZoneDelegate.invokeTask (zone.js:401:60)
我无法识别错误,请帮忙..我到处检查过,甚至使用了chatGPT并尝试了响应,但没有成功。
下面是我的 user-register.component.html 代码:
<div class="row">
<div class="col-6 m-auto">
<mat-card class="card m-auto">
<mat-card-header class="card-header">
<mat-card-title>Register</mat-card-title>
<mat-card-subtitle>Register to unlock more features</mat-card-subtitle>
</mat-card-header>
<mat-card-content class="card-body">
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()" #ngForm>
<div class="form-group col-12">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" formControlName="userName">
<span *ngIf="!userName.valid && userName.touched" class="error-block">
Please provide name!
</span>
</div>
<div class="form-group col-12">
<label for="email" class="form-label">Email</label>
<input type="text" class="form-control" formControlName="email">
<span *ngIf="!email.valid && email.touched" class="error-block">
<span *ngIf="email.hasError('required')">
Please provide email ID!
</span>
<span *ngIf="email.hasError('email')">
Please provide a valid email ID!
</span>
</span>
</div>
<div class="form-group col-12">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" formControlName="password">
<span *ngIf="!password.valid && password.touched" class="error-block">
<span *ngIf="password.hasError('minlength')">Please should not be less than 8 characters</span>
<span *ngIf="password.hasError('required')">Please provide password</span>
</span>
</div>
<div class="form-group col-12">
<label for="cpassword" class="form-label">Confirm Password</label>
<input type="password" class="form-control" formControlName="cpassword">
<span *ngIf="!confirmPassword.valid && confirmPassword.touched" class="error-block">
<span *ngIf="confirmPassword.hasError('minlength')">Please should not be less than 8 characters</span>
<span *ngIf="confirmPassword.hasError('required')">Please provide password</span>
</span>
</div>
<div class="form-group col-12">
<label for="mobile" class="form-label">Mobile</label>
<input type="text" class="form-control" formControlName="mobile">
<span *ngIf="!mobile.valid && mobile.touched" class="error-block">
<span *ngIf="mobile.hasError('minlength')">Please should not be less than 10 characters</span>
<span *ngIf="mobile.hasError('required')">Please provide password</span>
</span>
</div>
<br/>
<div class="form-group col-12">
<button type="submit" class="btn btn-primary">Save</button>
<button type="reset" class="btn btn-secondary ml-2">Cancel</button>
</div>
</form>
</mat-card-content>
</mat-card>
</div>
</div>
这是我的 user-register.component.ts 文件:
import { Component, OnInit } from '@angular/core';
import { AbstractControl, FormControl, FormGroup, Validators, } from '@angular/forms';
@Component({
selector: 'app-user-register',
templateUrl: './user-register.component.html',
styleUrl: './user-register.component.css'
})
export class UserRegisterComponent implements OnInit {
registrationForm: FormGroup;
constructor() { }
ngOnInit() {
this.registrationForm = new FormGroup({
userName: new FormControl('', Validators.required),
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required, Validators.minLength(8)]),
confirmPassword: new FormControl('', [Validators.required]),
mobile: new FormControl('', [Validators.required, Validators.maxLength(10)])
},
{
validators: this.passwordMatchingValidator,
}
)
}
passwordMatchingValidator(control: AbstractControl): {[key: string]: boolean} | null {
return control.get('password')?.value === control.get('confirmPassword')?.value ? null : {mismatch: true};
}
get userName() {
return this.registrationForm.get('userName') as FormControl;
}
get email() {
return this.registrationForm.get('email') as FormControl;
}
get password() {
return this.registrationForm.get('password') as FormControl;
}
get confirmPassword() {
return this.registrationForm.get('confirmPassword') as FormControl;
}
get mobile() {
return this.registrationForm.get('mobile') as FormControl;
}
onSubmit() {
console.log(this.registrationForm);
}
}
我所看到的是您在确认密码表单字段上有一个拼写错误,您将名称指定为
cpassword
而不是 confirmPassword
。
<div class="form-group col-12">
<label for="confirmPassword" class="form-label">Confirm Password</label>
<input type="password" class="form-control" formControlName="confirmPassword">
<span *ngIf="!confirmPassword.valid && confirmPassword.touched" class="error-block">
<span *ngIf="confirmPassword.hasError('minlength')">Please should not be less than 8 characters</span>
<span *ngIf="confirmPassword.hasError('required')">Please provide password</span>
</span>
</div>
模型和视图表单控件必须具有相同的名称!但我从来没有能够复制你的问题,如果它仍然没有解决,分享回 stackblitz 并复制问题!
import { bootstrapApplication } from '@angular/platform-browser';
import { Component, OnInit } from '@angular/core';
import {
AbstractControl,
FormControl,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import 'zone.js';
import { CommonModule } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { MatInputModule } from '@angular/material/input';
@Component({
selector: 'app-root',
standalone: true,
imports: [ReactiveFormsModule, CommonModule, MatCardModule, MatInputModule],
template: `
<div class="row">
<div class="col-6 m-auto">
<mat-card class="card m-auto">
<mat-card-header class="card-header">
<mat-card-title>Register</mat-card-title>
<mat-card-subtitle>Register to unlock more features</mat-card-subtitle>
</mat-card-header>
<mat-card-content class="card-body">
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()" #ngForm>
<div class="form-group col-12">
<label for="name" class="form-label">Name</label>
<input type="text" class="form-control" formControlName="userName">
<span *ngIf="!userName.valid && userName.touched" class="error-block">
Please provide name!
</span>
</div>
<div class="form-group col-12">
<label for="email" class="form-label">Email</label>
<input type="text" class="form-control" formControlName="email">
<span *ngIf="!email.valid && email.touched" class="error-block">
<span *ngIf="email.hasError('required')">
Please provide email ID!
</span>
<span *ngIf="email.hasError('email')">
Please provide a valid email ID!
</span>
</span>
</div>
<div class="form-group col-12">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" formControlName="password">
<span *ngIf="!password.valid && password.touched" class="error-block">
<span *ngIf="password.hasError('minlength')">Please should not be less than 8 characters</span>
<span *ngIf="password.hasError('required')">Please provide password</span>
</span>
</div>
<div class="form-group col-12">
<label for="confirmPassword" class="form-label">Confirm Password</label>
<input type="password" class="form-control" formControlName="confirmPassword">
<span *ngIf="!confirmPassword.valid && confirmPassword.touched" class="error-block">
<span *ngIf="confirmPassword.hasError('minlength')">Please should not be less than 8 characters</span>
<span *ngIf="confirmPassword.hasError('required')">Please provide password</span>
</span>
</div>
<div class="form-group col-12">
<label for="mobile" class="form-label">Mobile</label>
<input type="text" class="form-control" formControlName="mobile">
<span *ngIf="!mobile.valid && mobile.touched" class="error-block">
<span *ngIf="mobile.hasError('minlength')">Please should not be less than 10 characters</span>
<span *ngIf="mobile.hasError('required')">Please provide password</span>
</span>
</div>
<br/>
<div class="form-group col-12">
<button type="submit" class="btn btn-primary">Save</button>
<button type="reset" class="btn btn-secondary ml-2">Cancel</button>
</div>
</form>
</mat-card-content>
</mat-card>
</div>
</div>
`,
})
export class App {
registrationForm!: FormGroup;
constructor() {}
ngOnInit() {
this.registrationForm = new FormGroup(
{
userName: new FormControl('', Validators.required),
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [
Validators.required,
Validators.minLength(8),
]),
confirmPassword: new FormControl('', [Validators.required]),
mobile: new FormControl('', [
Validators.required,
Validators.maxLength(10),
]),
},
{
validators: this.passwordMatchingValidator,
}
);
}
passwordMatchingValidator(
control: AbstractControl
): { [key: string]: boolean } | null {
return control.get('password')?.value ===
control.get('confirmPassword')?.value
? null
: { mismatch: true };
}
get userName() {
return this.registrationForm.get('userName') as FormControl;
}
get email() {
return this.registrationForm.get('email') as FormControl;
}
get password() {
return this.registrationForm.get('password') as FormControl;
}
get confirmPassword() {
return this.registrationForm.get('confirmPassword') as FormControl;
}
get mobile() {
return this.registrationForm.get('mobile') as FormControl;
}
onSubmit() {
console.log(this.registrationForm.valid);
}
}
bootstrapApplication(App);