1

我很难验证角度材料表。我需要禁用保存按钮,直到所有字段都填写在垫表中。

我尝试使用模板驱动和反应方式的表单来做到这一点,但失败了。

这是html代码

<mat-card class="card">
  <mat-card-title fxLayout.gt-xs="row" fxLayout.xs="columin">
    <h3>Product Groups Editor</h3>
  </mat-card-title>
  <mat-card-content>
    <div class="data-container">
      <table mat-table [dataSource]="dataSource" matSort>
        <tr mat-header-row *matHeaderRowDef="displayedColumns sticky: true"></tr>
        <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

        <ng-container matColumnDef="englishName">
          <th mat-header-cell *matHeaderCellDef mat-sort-header class="table-header">English Name</th>
          <td mat-cell *matCellDef="let element">
            <input [disabled]="!element.active" [(ngModel)]="element.englishName" value="{{element.englishName}}">
          </td>
        </ng-container>

        <ng-container matColumnDef="color">
          <th mat-header-cell *matHeaderCellDef class="table-header">Color</th>
          <td mat-cell *matCellDef="let element">
            <input [disabled]="!element.active" [(colorPicker)]="element.color" [style.background]="element.color" />
          </td>
        </ng-container>

        <ng-container matColumnDef="level">
          <th mat-header-cell *matHeaderCellDef mat-sort-header class="table-header">Level</th>
          <td mat-cell *matCellDef="let element">
            <mat-form-field appearance="outline">
              <mat-select placeholder="Level" [disabled]="!element.active" [(ngModel)]="element.groupLevel">
                <mat-option *ngFor="let eachLevel of allGroupLevel" [value]="eachLevel.groupLevelId">
                  {{eachLevel.name}}
                </mat-option>
              </mat-select>
            </mat-form-field>
          </td>
        </ng-container>

      </table>
    </div>
    <div>
      <button id="addButton" (click)="addGroup()" mat-raised-button color="primary">
        <mat-icon>add</mat-icon>Add Group
      </button>
      <button id="saveButton" (click)="saveGroups()" mat-raised-button color="primary">
        <mat-icon>save</mat-icon>Save Groups
      </button>
    </div>
  </mat-card-content>
</mat-card>

如果有人可以提供帮助,我将不胜感激。

4

1 回答 1

0

我不是 Angular 方面的专家,并且可能没有以最好的方式做到这一点。但是,我已经完成了它并让它工作了,所以这里是如何:

在 Component 模块中,为 HTML 中的每个控件创建一个 FormControl。对于表格,我使用了一个 FormGroups 数组,每个 FormGroup 都有用于表格单行的控件。这些控件和组是基于 MatTableDataSource 内容创建的。

我下面的示例代码使用具有几个属性的主对象和一个详细对象数组,每个对象都有 3 个属性。

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder }   from '@angular/forms';
import { MatTableDataSource }  from '@angular/material';

class Detail {
  id: number;
  name: string;
  value: number;
};

class Master {
  id: number;
  name: string;
  details: Detail[];
};

@Component({
  selector: 'app-master-detail',
  templateUrl: './master-detail.component.html',
  styleUrls: ['./master-detail.component.css']
})
export class MasterDetailComponent implements OnInit {

columnsToDisplay = ['detail_id', 'detail_name', 'detail_value'];

master: Master;
form: FormGroup;
dataSource = new MatTableDataSource([]);
minMasterId = 1;
maxMasterId = 100;
minDetailId = 1;
maxDetailId = 10;

constructor(private fb: FormBuilder) { }

ngOnInit() {

  // Add some code here to get your source data and load it into this.master
  // ...
  // I've added some dummy data to show the principle.
  this.master = {
    id: 1,
    name: "myMaster",
    details: [
      { id: 1, name: "myDetail1", value: 100 },
      { id: 2, name: "myDetail2", value: 200 }
    ]
  };

  // Create the FormControls for the Master.
  this.form = this.fb.group({
      id:      new FormControl(this.master.id, [Validators.required, Validators.min(this.minMasterId), Validators.max(this.maxMasterId)]),
      name:    new FormControl(this.master.name, [Validators.required]),
      details: this.fb.array([])
    });

  // Load the detail objects into the MatTableDataSource.
  this.dataSource.data = this.master.details;

  // For each detail object:
  // 1) Create a FormGroup containing FormControls for all the properties.
  // 2) Add the FormGroup into an array.
  let detailsArray = this.fb.array([]);
  this.dataSource.data.forEach(detail => {
    let formGroupForThisDetail = this.fb.group({
      detail_id:    new FormControl(detail.id,      [Validators.required, Validators.min(this.minDetailId), Validators.max(this.maxDetailId)]),
      detail_name:  new FormControl(detail.name,    [Validators.required]),
      detail_value: new FormControl(detail.value,   [Validators.required, Validators.min(0)]),
    });
    detailsArray.push(formGroupForThisDetail);
  });

  // Add the finished array onto the top-level form.
  this.form.setControl('details', detailsArray);
}

因此,现在表格中每个对象的每个属性都有一个 FormControl,并且 FormControl 包含适用于每个属性的验证器。

这些 FormControl 在 HTML 中的引用如下:

<div class="title">
  <h2>View/Edit Master - {{name.value}}</h2>
</div>

<mat-form-field class="master-field-id">
  <input matInput placeholder="Master ID" formControlName="id" type="number" min="{{minMasterId}}" max="{{maxMasterId}}">
</mat-form-field>

<mat-form-field class="master-field-name">
  <input matInput placeholder="Name" formControlName="name">
</mat-form-field>

<mat-table formArrayName="details" [dataSource]="dataSource" matSort>
  <ng-container matColumnDef="detail_id">
    <mat-header-cell *matHeaderCellDef> ID </mat-header-cell>
    <mat-cell *matCellDef="let detail; let rowIndex=index" [formGroupName]="rowIndex">
      <input matInput placeholder="ID" type="number" formControlName="detail_id" min="{{minDetailId}}"
        max="{{maxDetailId}}">
    </mat-cell>
  </ng-container>
  <ng-container matColumnDef="detail_name">
    <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
    <mat-cell *matCellDef="let detail; let rowIndex=index" [formGroupName]="rowIndex">
      <input matInput placeholder="Name" formControlName="detail_name">
    </mat-cell>
  </ng-container>
  <ng-container matColumnDef="detail_value">
    <mat-header-cell *matHeaderCellDef> Value </mat-header-cell>
    <mat-cell *matCellDef="let detail; let rowIndex=index" [formGroupName]="rowIndex">
      <input matInput placeholder="Value" type="number" formControlName="detail_value" min="0">
    </mat-cell>
  </ng-container>
  <mat-header-row *matHeaderRowDef="columnsToDisplay"></mat-header-row>
  <mat-row *matRowDef="let row; columns: columnsToDisplay"></mat-row>
</mat-table>

<button class="mat-raised-button mat-primary" [disabled]="form.invalid" (click)="onSave()">Save</button>

表单底部的“保存”按钮将根据所有属性上的所有验证器更改其状态(即,如果任何验证器无效,则整个表单无效并且按钮被禁用)。

您需要在某处实现“onSave()”才能实际进行保存。

于 2020-01-20T12:33:21.727 回答