In angular mat-table 根据rowIndex和columnIndex插入数据

In angular mat-table insert data based on rowIndex and columnIndex

我正在尝试创建一个 table 响应如下 行数 & 列数.

在这个 table 中,我有一个 objects 数组,带有 行索引号 列索引号,我试图将其相应地显示到 Angular Material Table component

{
 "Table": [
    {
      "NumCols": 4,
      "NumRows": 10,
      "TableData": [
        {
          "Id": "1",
          "ColumnIndex": 1,
          "ColumnSpan": 0,
          "RowIndex": 2,
          "RowSpan": 0,
          "Cell": "Data 1"
        },
        {
          "Id": "2",
          "ColumnIndex": 2,
          "ColumnSpan": 0,
          "RowIndex": 1,
          "RowSpan": 0,
          "Cell": "Data 2"
        },
        {
          "Id": "3",
          "ColumnIndex": 3,
          "ColumnSpan": 0,
          "RowIndex": 5,
          "RowSpan": 0,
          "Cell": "Data 3"
        },
        {
          "Id": "4",
          "ColumnIndex": 4,
          "ColumnSpan": 0,
          "RowIndex": 3,
          "RowSpan": 0,
          "Cell": "Data 4"
        },
        {
          "Id": "5",
          "ColumnIndex": 1,
          "ColumnSpan": 0,
          "RowIndex": 4,
          "RowSpan": 0,
          "Cell": "Data 5"
        },
        {
          "Id": "6",
          "ColumnIndex": 2,
          "ColumnSpan": 0,
          "RowIndex": 6,
          "RowSpan": 0,
          "Cell": "Data 6"
        },
        {
          "Id": "7",
          "ColumnIndex": 3,
          "ColumnSpan": 0,
          "RowIndex": 7,
          "RowSpan": 0,
          "Cell": "Data 7"
        },
        {
          "Id": "8",
          "ColumnIndex": 2,
          "ColumnSpan": 0,
          "RowIndex": 8,
          "RowSpan": 0,
          "Cell": "Data 8"
        },
        {
          "Id": "9",
          "ColumnIndex": 3,
          "ColumnSpan": 0,
          "RowIndex": 9,
          "RowSpan": 0,
          "Cell": "Data 9"
        },
        {
          "Id": "10",
          "ColumnIndex": 4,
          "ColumnSpan": 0,
          "RowIndex": 10,
          "RowSpan": 0,
          "Cell": "Data 10"
        }
      ]
    }
  ]
}

与此类似,没有任何 headers(Column1 等...)

我已经发布了 working solution on Github.

的完整源代码

首先,您需要声明一个接口,以便 TypeScript 知道您的 JSON 是什么数据类型。为简单起见,您可以将接口 属性 名称与 JSON 属性 名称匹配。您可以直接在 component.ts 文件或外部 .ts 文件中执行此操作。

// Create an interface for your data, so TypeScript knows what datatype to work with when
//    putting your data in the table.
export interface TableDataInterface {
  Id: string;
  ColumnIndex: number;
  ColumnSpan: number;
  RowIndex: number;
  RowSpan: number;
  Cell: string;
}

现在在你的 component.ts 文件中,声明三个数组:一个用于你的输入数据(从 JSON 响应中读取),一个用于 table 数据(什么您将在 HTML 中绑定),还有一个用于 table 列定义(Angular 对此技术要求的内容):

export class YourComponent {
    // ...

    // Declare a property on your component to hold the data for your table,
    //    and initialize it to an empty array.
    inputData: TableDataInterface[] = []

    // Declare a property on your component to hold the data to be displayed.
    //    This is what you will bind to from the HTML.
    tableData: string[][] = [];

    // Declare a property to hold the list of columns to display.
    tableColumns: string[] = [];

    // ...
}

在你的组件 class 内的适当函数内(我刚刚在 ngOnInit() 内写了我的),你现在有 4 个步骤要完成。

首先,从任何来源获取数据。下面的代码使用本地 JSON 文件。我有 。在从 API 连接到实时数据之前,这有利于测试。连接到实时数据源后,您需要用 API 代码替换 getData() 函数的内容。

import Table from './data/test-data.json'; // Added to support reading data from local json file.
import { TableDataInterface } from '../types/table-data.interface'; // import your interace.

// Added to support reading data from local json file.
let table_data = Table.Table;

export class YourComponent {
    // ...

    // Use the initialization (or whatever other appropriate function) to populate the
    //    data of your table.
    ngOnInit(): void {

        // 1. Get the data from whatever source you are getting it from.
          this.inputData = this.getData();

        // The next three steps go here ...
    }

// ...

// Put your code to get the table data in this function. Here a hard-coded value is
//    used as an example.
getData(): TableDataInterface[] {

    // NOTE: if your interface properties do not match exactly the json, you will
    //    need to convert between the two here before returning. In this example
    //    the two match, so the data can be directly returned.

    return table_data[0].TableData;
}

// ...
}

其次,根据 JSON 响应中的数据创建要绑定的二维数组:

// 2. Create a 2D array with a value for each cell initialized to empty string.
for (var row: number = 0; row < table_data[0].NumRows; row++) {

    // Initialize the row.
    this.tableData[row] = [];

    for (var col: number = 0; col < table_data[0].NumCols; col++) {

        // Initialize the cell in the row.
        this.tableData[row][col] = "";
    }
}

第三,为 Angular 创建列数组,以便在渲染 table:

时从中绘制
// 3. Create an entry in the table columns array for each column.
for (var col: number = 0; col < table_data[0].NumCols; col++) {

    // Angular requires a unique name for each column, so we will just
    //    use the index of that column for the name.
    this.tableColumns[col] = col.toString();
}

第四,使用 JSON 响应中的 ColumnIndex 和 RowIndex,将初始化二维数组的值替换为 JSON 响应中的值。

// 4. Now replace the values in the table data with the ones you want displayed.
for (var inputIndex: number = 0; inputIndex < this.inputData.length; inputIndex++) {

    // NOTE: the -1 for the column and row is to account for the fact that the input data
    //    is one-indexed, while the arrays are zero-indexed.
    this.tableData[this.inputData[inputIndex].RowIndex - 1][this.inputData[inputIndex].ColumnIndex - 1] = this.inputData[inputIndex].Cell;
}

最后,component.html 文件中的 HTML 会很短:

<!-- Bind the data source to the 2D data array in your corresponding .ts file. -->
<table mat-table [dataSource]="tableData">

  <!-- Define the column templates. Use an ngFor to create a template for
      each column in the array of columns. -->
  <mat-text-column *ngFor="let data of tableColumns"
                 [name]="data"></mat-text-column>

  <!-- Uncomment the following line if you want column headers. -->
  <!--<tr mat-header-row *matHeaderRowDef="tableColumns"></tr>-->
  <tr mat-row *matRowDef="let row; columns: tableColumns;"></tr>
</table>

使用问题中给出的 JSON 的结果将如下所示(来自 运行 本地主机 Github 上发布的代码的屏幕截图):

如果看起来不协调,请使用 table 样式。在上面的屏幕截图中,我使用了以下 CSS:

table {
    width: 600px;
    margin: 20px;
}

重要限制:该解决方案目前假定没有单元格数据跨越多行或多列。添加它会使事情变得更加困难!