首页 > 解决方案 > 带有动态标题和单元格的 Angular 7 材料表

问题描述

考虑到我从这样的 API 获得了一组对象(用户有选择框来选择年份、类型和输入值):

[
  {
    "year": 2019,
    "type": "Salaries",
    "value": 100
  },
  {
    "year": 2019,
    "type": "Projects",
    "value": 78
  },
  {
    "year": 2018,
    "type": "Projects",
    "value": 500
  },
  {
    "year": 2018,
    "type": "Others",
    "value": 500
  },
]

我需要像这样每年显示这些数据:

| Year | Salaries | Pojects | Others |
-------------------------------------
| 2019 |   100    | 78      |        |
-------------------------------------
| 2018 |          | 500     | 500    |

我无法弄清楚的部分是如何遍历数组以构建数组标题,然后每年将正确的值放在相应的类型上......感谢您的帮助。

标签: javascriptangulartypescript

解决方案


为了实现您的目标,您需要使用从 API 接收的数据创建一个新数组。为了给出我的解决方案,我假设您从 API 收到如下数据数组。

[{ "year": 2019, "type": "Salaries", "value": 100 },
 { "year": 2019, "type": "Projects", "value": 78 },
 { "year": 2018, "type": "Projects", "value": 500 },
 { "year": 2018, "type": "Others", "value": 500 },
 { "year": 2019, "type": "Others", "value": 230 },
 { "year": 2018, "type": "Salaries", "value": 900 }]

要在您的问题中的表格中显示上述数据,您必须将其转换为有意义的数组,如下所示。

[{ "year": 2019, "salary": 100, "project": 78, "other": 230 },
    { "year": 2018, "salary": 900, "project": 500, "other": 500 }]

我假设某年没有相同类型的重复记录,如下所示。

{ "year": 2019, "type": "Salaries", "value": 100 }
{ "year": 2019, "type": "Salaries", "value": 200 }

如果有像上面最后一个元素的重复值将被视为 value

您必须实现新函数来创建displayData数组,如下所示。

打字稿

export class MyComponent  {
  data = [
 { "year": 2019, "type": "Salaries", "value": 100 },
 { "year": 2019, "type": "Projects", "value": 78 },
 { "year": 2018, "type": "Projects", "value": 500 },
 { "year": 2018, "type": "Others", "value": 500 },
 { "year": 2019, "type": "Others", "value": 230 },
 { "year": 2018, "type": "Salaries", "value": 900 }];

displayData: any = [];

 constructor() {
   this.createDisplayData()
 }

 createDisplayData(): void {

   for (let i = 0; i < this.data.length; i++) {

      let type: string;

      if (this.data[i].type === "Salaries")
        type = 'salary';
      else if (this.data[i].type === "Projects") 
        type = 'project';
      else 
        type = 'other';

     const found = this.displayData.find(v => v.year === this.data[i].year);

     if (!found) {
       let object = {};
       object['year'] = this.data[i].year;
       object[type] = this.data[i].value
       this.displayData.push(object);
     }
     else {
       found[type] = this.data[i].value;
     }
   }
 }
}

HTML

<table style="width: 100%">
  <tr>
    <th>Year</th>
    <th>Salaries</th>
    <th>Pojects</th>
    <th>Others</th>
  </tr>
  <tr *ngFor="let data of displayData">
    <td style="text-align: center">{{data.year}}</td>
    <td style="text-align: center">{{data.salary}}</td>
    <td style="text-align: center">{{data.project}}</td>
    <td style="text-align: center">{{data.other}}</td>
  </tr>
</table>

在此处查找StackBlitz 演示

更新评论的建议。

其他可以做到这一点的方法是使用Array.reduce()函数而不是 for 循环,如下所示。

TS

 createDisplayData(): void {

   this.displayData = this.data.reduce((accumulator, currentValue) => {

     const found = accumulator.find(v => v.year === currentValue.year);
     if (!found) {

       let object = {};
       object['year'] = currentValue.year;
       object[currentValue.type] = currentValue.value;
       accumulator.push(object);
     } else {

       found[currentValue.type] = currentValue.value;
     }
     return accumulator;
   }, []);
 }

HTML

<table style="width: 100%">
  <tr>
    <th>Year</th>
    <th>Salaries</th>
    <th>Pojects</th>
    <th>Others</th>
  </tr>
  <tr *ngFor="let data of displayData">
    <td style="text-align: center">{{data.year}}</td>
    <td style="text-align: center">{{data.Salaries}}</td>
    <td style="text-align: center">{{data.Projects}}</td>
    <td style="text-align: center">{{data.Others}}</td>
  </tr>
</table>

查找StackBlitz 演示


推荐阅读