带有动态标题和单元格的Angular 7材质表

时间:2019-07-19 15:34:52

标签: javascript angular typescript

考虑到我从这样的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    |

我不知道的部分是如何遍历数组以构建数组头,然后每年将正确的值放在相应的类型上……感谢您的帮助。

3 个答案:

答案 0 :(得分:0)

由于要显示每年的数据,因此可以将年份用作唯一标识符。只需遍历对象并创建一个新对象,如下所示:

let dataPerYear = {}

response
    .forEach(function (data) {
        if (!dataPerYear[data.year]) {
            dataPerYear[data.year] = {
                year: data.year
            }
        }

        dataPerYear[data.year][data.type] = [data.value]
    })

应该导致的结果

{
    2019: {
        year: 2019,
        Salaries: 100,
        Projects: 78
    }
}

然后,如果您希望将其作为数组:

let arrayData = Object.values(result)

将导致:

[
    {
        year: 2019,
        Salaries: 100,
        Projects: 78
    }
]

答案 1 :(得分:0)

您可以使用reduce()将集合映射到该表所需的形状。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

然后像往常一样简单地将字段映射到Material表。

const 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
  },
]

const mappedData = data.reduce((acc, item) => {
  const match = acc.find(x => x.year === item.year);
  const transformed = {
    year: item.year,
    projects: item.type === "Projects" ? item.value : 0,
    salaries: item.type === "Salaries" ? item.value : 0,
    others: item.type === "Others" ? item.value : 0
  };
  
  if (match) {
    match.projects += transformed.projects;
    match.salaries += transformed.salaries;
    match.others += transformed.others;
  } else {
    acc.push(transformed);
  }
  
  return acc;
}, []);

console.log(mappedData);

答案 2 :(得分:0)

要实现您的目标,您需要使用从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 }

如果有重复的内容,如最后一个元素的值将作为值

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

TypeScript

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 Demo Here

  

通过评论更新建议。

您也可以使用 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 Demo