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

带模式行的Angular Mat Table设计创建及行新增动态适配实现咨询

Angular Material Table 带预设模式行动态新增实现方案

设计参考图

核心实现逻辑是提前定义好每行的字段规则、校验、默认值的模式模板,新增行时直接复用模板生成符合要求的空行,数据源更新后Mat Table会自动适配渲染:

1. 前置依赖导入

在对应模块文件中引入必要的Angular Material组件:

import { NgModule } from '@angular/core';
import { MatTableModule } from '@angular/material/table';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    MatTableModule,
    MatFormFieldModule,
    MatInputModule,
    MatButtonModule,
    FormsModule,
    ReactiveFormsModule
  ]
})
export class YourModule { }

2. 定义模式模板与数据源

在组件中提前声明固定的行模式模板,所有新增行都会继承该模板的配置:

import { Component } from '@angular/core';
import { MatTableDataSource } from '@angular/material/table';

// 行模式模板:定义每列的默认值、是否必填、是否禁用等规则
const ROW_PATTERN = {
  serialNo: null,
  itemName: { value: '', required: true, disabled: false },
  specification: { value: '', required: false, disabled: false },
  quantity: { value: 1, required: true, min: 1, disabled: false },
  unitPrice: { value: 0, required: true, min: 0, disabled: false },
  totalPrice: { value: 0, required: false, disabled: true } // 总金额自动计算,禁止编辑
}

@Component({
  selector: 'app-pattern-table',
  templateUrl: './pattern-table.component.html'
})
export class PatternTableComponent {
  // 表格显示列,和模式模板字段一一对应
  displayedColumns: string[] = ['serialNo', 'itemName', 'specification', 'quantity', 'unitPrice', 'totalPrice', 'action'];
  // 数据源初始化,默认生成1行符合模式的空行
  dataSource = new MatTableDataSource<any>([this.generateNewRow()]);

  // 生成符合模式的新行
  generateNewRow() {
    const newRow = JSON.parse(JSON.stringify(ROW_PATTERN));
    // 序号自动按行数生成
    newRow.serialNo = this.dataSource ? this.dataSource.data.length + 1 : 1;
    return newRow;
  }
}

3. 编写表格模板,动态适配规则

HTML模板中直接复用模式配置的规则,无需为新增行额外写适配逻辑:

<table mat-table [dataSource]="dataSource" class="w-full">
  <!-- 序号列 -->
  <ng-container matColumnDef="serialNo">
    <th mat-header-cell *matHeaderCellDef> 序号 </th>
    <td mat-cell *matCellDef="let element"> {{element.serialNo}} </td>
  </ng-container>

  <!-- 商品名称列 -->
  <ng-container matColumnDef="itemName">
    <th mat-header-cell *matHeaderCellDef> 商品名称 </th>
    <td mat-cell *matCellDef="let element">
      <ng-container *ngIf="!element.itemName.disabled">
        <mat-form-field appearance="fill" class="w-full">
          <input matInput [required]="element.itemName.required" [(ngModel)]="element.itemName.value">
        </mat-form-field>
      </ng-container>
      <span *ngIf="element.itemName.disabled">{{element.itemName.value}}</span>
    </td>
  </ng-container>

  <!-- 规格、数量、单价列逻辑和名称列一致,按模式配置渲染即可 -->

  <!-- 总金额列 -->
  <ng-container matColumnDef="totalPrice">
    <th mat-header-cell *matHeaderCellDef> 总金额 </th>
    <td mat-cell *matCellDef="let element">
      {{element.quantity.value * element.unitPrice.value | currency:'CNY'}}
    </td>
  </ng-container>

  <!-- 操作列 -->
  <ng-container matColumnDef="action">
    <th mat-header-cell *matHeaderCellDef> 操作 </th>
    <td mat-cell *matCellDef="let element; let idx = index">
      <!-- 只有最后一行显示新增按钮 -->
      <button mat-stroked-button color="primary" (click)="addRow()" *ngIf="idx === dataSource.data.length - 1">
        新增行
      </button>
      <button mat-stroked-button color="warn" (click)="deleteRow(idx)" *ngIf="dataSource.data.length > 1">
        删除
      </button>
    </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

4. 新增/删除行逻辑实现

新增行直接调用模板生成方法插入数据源,自动适配表格布局:

// 新增行
addRow() {
  // 可选:新增前校验当前最后一行必填项是否完成
  const lastRow = this.dataSource.data[this.dataSource.data.length - 1];
  if (lastRow.itemName.required && !lastRow.itemName.value) {
    // 此处可添加必填项未填的提示
    return;
  }
  this.dataSource.data.push(this.generateNewRow());
  // 触发数据源更新,强制表格重新渲染
  this.dataSource._updateChangeSubscription();
}

// 删除行
deleteRow(index: number) {
  this.dataSource.data.splice(index, 1);
  // 重新计算所有行的序号
  this.dataSource.data.forEach((row, i) => row.serialNo = i + 1);
  this.dataSource._updateChangeSubscription();
}

小提示:如果使用响应式表单实现,可将ROW_PATTERN转换为FormGroup模板,新增行时直接通过FormBuilder生成对应表单实例,校验规则会自动生效,适配性更强。

内容的提问来源于stack exchange,提问作者Fahad Noor Khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 05:39:03