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

Angular 6中如何实现Mat表格内每行独立的Mat输入文本框验证?

Angular 6中如何实现Mat表格内每行独立的Mat输入文本框验证?

我完全理解你现在遇到的麻烦——在Mat表格里给每行加输入框时,所有行的输入内容和验证提示都同步了,这显然不是你想要的效果。你提到尝试过FormArray但没成功,那咱们一步步把这个问题解决掉。

问题根源

你之前的写法不管是用单个FormControl还是错误的FormArray用法,本质上都是让所有行共用了同一个表单控件,所以输入内容会串在一起,验证也会同时作用在所有行上。想要每行独立,必须给每一行分配一个专属的FormControl,然后用FormArray来管理这些控件。

正确实现步骤

1. 在TS文件中构建包含FormArray的表单

首先,我们要根据表格的数据源长度,为每行创建一个带验证规则的FormControl,然后把这些控件放进FormArray里,再包裹到一个FormGroup中。

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormArray, Validators } from '@angular/forms';
// 导入你的数据源相关类型,比如:
// import { YourDataType } from './your-data-type';

@Component({
  selector: 'app-your-component',
  templateUrl: './your-component.component.html',
  styleUrls: ['./your-component.component.css']
})
export class YourComponent implements OnInit {
  commentsForm: FormGroup;
  dataSource: any; // 替换成你的实际数据源(比如MatTableDataSource<YourDataType>)
  displayedColumns: string[] = ['cmts', /* 其他列名 */];
  submitted = false;

  constructor(private fb: FormBuilder) {}

  ngOnInit(): void {
    // 初始化FormArray:为数据源的每一行创建一个带验证的FormControl
    this.initCommentsForm();

    // 监听数据源变化,如果数据更新(比如分页、过滤),同步更新FormArray
    this.dataSource.connect().subscribe(data => {
      this.refreshCommentsForm(data);
    });
  }

  // 初始化表单
  private initCommentsForm(): void {
    const initialControls = this.dataSource.data.map(() => 
      this.fb.control('', [
        Validators.required,
        Validators.minLength(10),
        Validators.maxLength(40)
      ])
    );

    this.commentsForm = this.fb.group({
      commentsArray: this.fb.array(initialControls)
    });
  }

  // 数据源变化时刷新FormArray
  private refreshCommentsForm(data: any[]): void {
    const newControls = data.map(() => 
      this.fb.control('', [
        Validators.required,
        Validators.minLength(10),
        Validators.maxLength(40)
      ])
    );
    
    this.commentsArray.clear();
    newControls.forEach(control => this.commentsArray.push(control));
  }

  // 获取FormArray的快捷方法,方便模板调用
  get commentsArray(): FormArray {
    return this.commentsForm.get('commentsArray') as FormArray;
  }

  // 表单提交处理
  onSubmit(): void {
    this.submitted = true;

    // 如果表单无效,标记所有控件为已触摸,强制显示错误
    if (this.commentsForm.invalid) {
      this.commentsArray.controls.forEach(control => control.markAsTouched());
      return;
    }

    // 获取每行的评论值,和数据源结合
    const comments = this.commentsArray.value;
    const dataWithComments = this.dataSource.data.map((item, index) => ({
      ...item,
      cmnts: comments[index]
    }));

    // 这里可以把dataWithComments发送到后端,比如:
    // this.yourService.saveComments(dataWithComments).subscribe(...);
  }
}

2. 修改HTML模板,绑定每行的专属控件

把表单包裹在表格外面,然后在matCellDef里通过rowIndex绑定到FormArray中对应的控件,这样每行的输入框就独立了。

<form [formGroup]="commentsForm">
  <table mat-table [dataSource]="dataSource" class="" matSort>
    <!-- 其他列的定义(保留你原来的代码) -->

    <ng-container matColumnDef="cmts">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Comments </th>
      <td mat-cell *matCellDef="let element; let rowIndex = index">
        <span *ngIf="element?.sts=='A'">
          <mat-form-field>
            <input 
              matInput 
              [formControl]="commentsArray.at(rowIndex)"
              placeholder="Enter your comments"
            >
            <mat-error *ngIf="commentsArray.at(rowIndex).invalid && (commentsArray.at(rowIndex).touched || submitted)">
              <span *ngIf="commentsArray.at(rowIndex).errors?.required">Comments are required</span>
              <span *ngIf="commentsArray.at(rowIndex).errors?.minlength">Minimum length should be 10 characters</span>
              <span *ngIf="commentsArray.at(rowIndex).errors?.maxlength">Maximum length should be 40 characters</span>
            </mat-error>
          </mat-form-field>
        </span>
      </td>
    </ng-container>

    <!-- 表格行渲染 -->
    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
  </table>

  <!-- 提交按钮(根据你的需求添加) -->
  <button mat-raised-button color="primary" (click)="onSubmit()">Submit Comments</button>
</form>

关键注意点

  • 数据源同步:如果你的表格有分页、过滤或排序功能,一定要监听数据源的变化,同步更新FormArray的长度,否则会出现控件和行不匹配的情况。
  • 验证触发:提交表单时,记得手动标记所有控件为touched,这样即使用户没点击过输入框,也会显示错误提示。
  • 控件独立性:通过rowIndex绑定commentsArray.at(rowIndex),确保每行的输入框对应唯一的FormControl,这样输入和验证就不会互相影响了。

备注:内容来源于stack exchange,提问作者sai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.23 12:37:41