You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:37:11