Angular响应式表单验证报错:声明错误提示信息时出现问题
Angular响应式表单验证错误提示报错问题
我在开发Angular响应式表单验证功能时,声明错误提示信息时遇到报错,相关代码如下:
HTML 代码
<h1 mat-dialog-title>Add Product Form</h1> <div id="form"> <form [formGroup]="ProductForm" style="background-color: black"> <p> <mat-form-field appearance="outline"> <mat-label>Product Name</mat-label> <input formControlName="productName" matInput placeholder="Enter Product Name" /> <div *ngIf="ProductForm.controls['productName'].invalid && (ProductForm.controls['productName'].dirty || ProductForm.controls['productName'].touched)" class="alert" > <div *ngIf="ProductForm.controls.productName.errors.required"> This field requires entries </div> </div> </mat-form-field> <mat-form-field appearance="outline"> <mat-label>Product category</mat-label> <mat-select formControlName="productCategory" placeholder="Category"> <mat-option value="Fruits">Fruits</mat-option> <mat-option value="Vegitables">Vegitables</mat-option> <mat-option value="Pulses">Pulses</mat-option> <mat-option value="Liquides">Liquides</mat-option> </mat-select> </mat-form-field> <mat-form-field appearance="outline"> <mat-label>Choose a date</mat-label> <input formControlName="date" matInput [matDatepicker]="picker" /> <mat-datepicker-toggle matIconSuffix [for]="picker"> </mat-datepicker-toggle> <mat-datepicker #picker> </mat-datepicker> </mat-form-field> <mat-label for=""> Product Freshness </mat-label> <mat-radio-group formControlName="freshness" class="example-radio-group"> <mat-radio-button *ngFor="let fresh of FreshnessList" [value]="fresh" class="example-radio-button" > {{ fresh }} </mat-radio-button> </mat-radio-group> <mat-form-field appearance="outline"> <mat-label>Price</mat-label> <input formControlName="productPrice" matInput type="number" placeholder="Enter Product Price" /> </mat-form-field> <mat-form-field appearence="outline"> <mat-label>Comment</mat-label> <textarea formControlName="comment" matInput></textarea> </mat-form-field> </p> </form> <div mat-dialogue-action [align]="'end'"> <button mat-raised-button color="warn" mat-dialog-close="">Close</button> <button style="margin-left: 8px" mat-raised-button color="primary" mat-dialog-close="" (click)="addProduct()" > {{ACTION}} </button> </div> </div>
TypeScript 代码
import { Component, Inject, OnInit } from "@angular/core"; import { FormGroup, FormBuilder, Validators } from "@angular/forms"; import { ApiService } from "../services/api.service"; import { MatDialogRef, MAT_DIALOG_DATA } from "@angular/material/dialog"; @Component({ selector: 'app-dialogue', templateUrl: './dialogue.component.html', styleUrls: ['./dialogue.component.scss'] }) export class DialogueComponent implements OnInit { FreshnessList = [ "Fresh", "3 days old", "5 days old", "1 week old", "Not for sale", ]; ProductForm!: FormGroup; ACTION: string = "Save"; constructor( private formbuilder: FormBuilder, private api: ApiService, private dialogueRef: MatDialogRef<DialogueComponent>, @Inject(MAT_DIALOG_DATA) public editData: any ) {} ngOnInit(): void { this.ProductForm = this.formbuilder.group({ id: "", productName: ["", Validators.required], productCategory: ["", Validators.required], date: ["", Validators.required], freshness: ["", Validators.required], productPrice: ["", Validators.required], comment: ["", Validators.required], }); if (this.editData) { this.ACTION = "UPDATE"; this.ProductForm.controls["id"].setValue(this.editData.id); this.ProductForm.controls["productName"].setValue( this.editData.productName ); this.ProductForm.controls["productCategory"].setValue( this.editData.productCategory ); this.ProductForm.controls["date"].setValue(this.editData.date); this.ProductForm.controls["freshness"].setValue(this.editData.freshness); this.ProductForm.controls["productPrice"].setValue( this.editData.productPrice ); this.ProductForm.controls["comment"].setValue(this.editData.comment); } console.log(this.editData); } addProduct() { console.log("add product"); if (!this.editData) { console.log(" is editable"); console.log(this.ProductForm?.value); if (this.ProductForm.valid) { const tempData: any = this.ProductForm.value; const formData: any = { ...tempData, ["id"]: tempData.productName }; this.api.postProduct(formData).subscribe({ next: (res) => { alert("product added successfully"); this.ProductForm.reset(); this.dialogueRef.close("save"); }, error: () => { alert("error while adding the product"); }, }); } } else { this.updateProduct(); } } updateProduct() { this.api.putProduct(this.ProductForm.value, this.editData.id).subscribe({ next: (res) => { alert("Product Updated successfully"); this.ProductForm.reset(); this.dialogueRef.close("update"); }, error: () => { alert("Error while updating "); }, }); } }
问题分析与修复方案
1. 空指针错误(核心报错原因)
模板中直接访问ProductForm.controls.productName.errors.required会触发空指针异常:当控件未触发校验或无错误时,errors属性为null,直接访问required会抛出错误。
修复方式:使用Angular表单控件内置的hasError()方法替代直接访问errors属性:
<div *ngIf="ProductForm.controls['productName'].hasError('required')"> This field requires entries </div>
2. 拼写错误
mat-dialogue-action应为mat-dialog-actions(Material Dialog操作栏指令拼写错误)appearence应为appearance(comment字段的mat-form-field属性拼写错误)
3. 代码优化(可选)
在组件中添加getter方法获取表单控件,简化模板代码:
get productName() { return this.ProductForm.get('productName'); }
模板中可简化为:
<div *ngIf="productName.invalid && (productName.dirty || productName.touched)" class="alert"> <div *ngIf="productName.hasError('required')"> This field requires entries </div> </div>
内容的提问来源于stack exchange,提问作者Arun Tripathi
相关产品推荐
相关产品推荐

