【问题标题】:Angular 6 ngFor list of tables grouped by keyAngular 6 ngFor 按键分组的表列表
【发布时间】:2018-10-27 23:06:46
【问题描述】:

我的 Angular 6 应用需要显示一个表格列表,其中一个表格是对其组成元素的一组化学分析。

假设我有一种金属合金A。我对其进行了不同的化合物分析以找出其化学成分:Fe:0.001%、Cu:0.042% 等。

这是我的数据源,它只是一个带有 mocks 的 typescript 文件

import { Certificate } from './certificate';

export const CERTIFICATES: Certificate[] = [
    { serie: '1050 AJ', ident: 'Fe', moy_certified: 0.297 },
    { serie: '1050 AJ', ident: 'Cu', moy_certified: 0.04 },
    { serie: '1050 AJ', ident: 'Mn', moy_certified: 0.0374 }, 
    { serie: 'X332.0 AC', ident: 'V', moy_certified: 0.019 },
    { serie: 'X4002 AA', ident: 'Mn', moy_certified: 0.037 }
];

我想使用 Angular 6 以 HTML 格式在表格列表中显示这些数据,其中一个系列的每个分析都按如下方式分组:

Serie: 1050 AJ
-------------------------
| Element | Composition |
-------------------------
|    Fe   |    0.0297   |
-------------------------
|    Cu   |    0.04     |
-------------------------
|    Mn   |    0.0374   |

Serie: X332.0 AC
-------------------------
| Element | Composition |
-------------------------
|    V    |    0.019    |

Serie: X332.0 AC
-------------------------
| Element | Composition |
-------------------------
|    Mn   |    0.037    |

我的 HTML 文件现在看起来像这样

<ul class="cert-result">
    <li *ngFor="let certificate of certificates">
      <table>
        <tr>
          <th>Serie</th>
          <th>Element</th>
          <th>Composition</th>
        </tr>
        <tr>
          <td>{{certificate.serie}}</td>
          <td>{{certificate.ident}}</td>
          <td>{{certificate.moy_certifiee}}</td>
        </tr>
      </table>
    </li>
  </ul>

显然,这不是正确的做法,因为它为我的数据源的每个元素创建了一个表格。

【问题讨论】:

  • 你需要改变数据结构
  • 如果可能的话,我想保持数据结构不变,而是使用 Angular 来解决问题。
  • @JimP。您可以保留原始 DS 而不更改它,但最终您将从系列属性中获取值并将它们设置为键
  • @Jim P. 更多botes 的答案应该是正确的答案。图书馆的存在是有原因的。成为一个更好的程序员也意味着聪明并使用那里的资源......比如库/框架。你知道在你的情况下你正在使用 Angular ...如果你根本不想使用库,你应该使用 plan vanillaJS 构建你的 SPA
  • 我已经知道了,但我一直在寻找不使用库的解决方案,因为我当前的上下文不允许我这样做。

标签: angular angular6 angular-ngfor


【解决方案1】:

你必须改变数据结构。

解决方案。

你的数据

export const CERTIFICATES: Certificate[] = [
    { serie: '1050 AJ', ident: 'Fe', moy_certified: 0.297 },
    { serie: '1050 AJ', ident: 'Cu', moy_certified: 0.04 },
    { serie: '1050 AJ', ident: 'Mn', moy_certified: 0.0374 }, 
    { serie: 'X332.0 AC', ident: 'V', moy_certified: 0.019 },
    { serie: 'X4002 AA', ident: 'Mn', moy_certified: 0.037 }
];

在您的组件中创建一个方法。比如说formatedData()

import { CERTIFICATES } from './certificate';


class AppComponent {
  //Todo...

  objectKey(obj) {
    return Object.keys(obj);
  }

  formatedCerts() {
      return CERTIFICATES.reduce((prev, now) => {
        if (!prev[now.serie]) {
          prev[now.serie] = [];
        }

        prev[now.serie].push(now);
        return prev;
      }, {});

    /*
       Now your data : { "1050 AJ": [ .... ], "X332.0 AC": [...], ... }
    */

  }

}

现在在模板中:

    <ul class="cert-result">
      <li *ngFor="let key of objectKey(formatedCerts())">
        <span>{{key}}</span>
        <table>
          <tr>
            <th>Élément</th>
            <th>Moy. Certifiée</th>
          </tr>
          <tr *ngFor="let certificate of formatedCerts()[key]">
            <td>{{certificate.ident}}</td>
            <td>{{certificate.moy_certifiee}}</td>
          </tr>
    </table>
      </li>
    </ul>

如果要优化,请将formatedCerts()的数据存入一个变量中。

【讨论】:

  • Object.keys(formatedData) 不起作用。模板会给你一个错误
  • 已修复。 “在”
  • for in 也不起作用,它会给你错误“嵌入模板上的任何指令都没有使用属性绑定 ngForIn。”
  • 另外,如果您将代码中的“in”更改为 of,则会出现以下错误:“Cannot find a different support object '[object Object]' of type 'object'。NgFor 仅支持绑定到诸如数组之类的可迭代对象。”我也不得不修改我的答案 :( 为了得到一个可行的解决方案
  • 它按需要工作,不涉及外部库。我编辑了 HTML 以仅重复每个键的元素行。
【解决方案2】:

您可以在 Angular 应用中使用下划线轻松存档。

how to use underscore.js library in angular 2

    groupedSeriesNames = []
        groupedSeries = []
            Certificate[] = [
                { serie: '1050 AJ', ident: 'Fe', moy_certified: 0.297 },
                { serie: '1050 AJ', ident: 'Cu', moy_certified: 0.04 },
                { serie: '1050 AJ', ident: 'Mn', moy_certified: 0.0374 }, 
                { serie: 'X332.0 AC', ident: 'V', moy_certified: 0.019 },
                { serie: 'X4002 AA', ident: 'Mn', moy_certified: 0.037 }
            ];

this.groupedSeries = _.groupBy(this.Certificate, certificate=>certificate.serie);

    this.groupedSeriesNames = Object.keys(this.groupedSeries)

certificate.serie 将成为他们的密钥,您可以将 certificate.serie 更改为任何其他属性,例如 iden 或任何您需要的属性

你的html

<ul class="cert-result">
    <li *ngFor="let key of groupedSeriesNames">
      <table *ngFor="let certificate of groupedSeries[key]">
        <tr>
          <th>Serie</th>
          <th>Element</th>
          <th>Composition</th>
        </tr>
        <tr>
          <td>{{certificate.serie}}</td>
          <td>{{certificate.ident}}</td>
          <td>{{certificate.moy_certifiee}}</td>
        </tr>
      </table>
    </li>
  </ul>

【讨论】:

  • 做这种简单任务的外部库?
  • @RitwickDey 每个人都使用下划线,你会得到一个更易读和更清晰的代码
【解决方案3】:
  <table >
    <tr>
      <th>Serie</th>
      <th>Element</th>
      <th>Composition</th>
    </tr>
    <ng-container *ngFor="let certificate of certs">
    <tr *ngIf="certificate.serie == '1050 AJ'">
      <td>{{certificate.serie}}</td>
      <td>{{certificate.ident}}</td>
      <td>{{certificate.moy_certified}}</td>
    </tr>
    <tr *ngIf="certificate.serie == 'X332.0 AC'">
      <td>{{certificate.serie}}</td>
      <td>{{certificate.ident}}</td>
      <td>{{certificate.moy_certified}}</td>
    </tr>
    <tr *ngIf="certificate.serie == 'X4002 AA'">
      <td>{{certificate.serie}}</td>
      <td>{{certificate.ident}}</td>
      <td>{{certificate.moy_certified}}</td>
    </tr>
    </ng-container>
</table>

演示:https://stackblitz.com/edit/angular-3tvwgv

不是很简洁。希望其他人可以提供更好的解决方案。

【讨论】:

  • 就像提示一样,代码应该尽量避免使用静态变量。如果这个表有百万条记录呢?让一切尽可能动态化是一个好习惯
  • 静态值 :(
  • @PatricioVargas,你是对的,我知道。只是为了简单的解决方案。
猜你喜欢
  • 2019-03-03
  • 2018-12-21
  • 2018-09-02
  • 1970-01-01
  • 2018-10-09
  • 2019-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多