3

Having an array like this(e.g. products in a basket)

[{
    "name": "item 1",
    "id": 1,
    "price": 10
},
{
    "name": "item 2",
    "id": 2,
    "price": 20
},
{
    "name": "item 1",
    "id": 1,
    "price": 10
},
{
    "name": "item 3",
    "id": 3,
    "price": 30
}]

How can I do a *ngFor in Angular 8 in order to print an output like:

  • 2x item 1, subtotal 20
  • 1x item 2, subtotal 20
  • 1x item 3, subtotal 30

So basically I wish to wrap up by name(or ID) the duplicate items and show only one row for them. I should also count the occurrences and the subtotal of them

Random
  • 3,158
  • 1
  • 15
  • 25
Andy
  • 209
  • 2
  • 11

2 Answers2

4

You could preprocess array before usage. Like: Most efficient method to groupby on an array of objects

And even better - to perform preprocessing in pipe and use it like:

<div *ngFor="entry in items | customGroupByPype">
Alex Vovchuk
  • 2,828
  • 4
  • 19
  • 40
  • Can you please give me an example of how I can wrap up the duplicates and calculate their number and subtotal? – Andy Sep 11 '19 at 13:52
  • use custom pipe: https://angular.io/guide/pipes#custom-pipes And set logic there similar to answers from the link above – Alex Vovchuk Sep 11 '19 at 13:58
1

Try like this:

Typescript:

export class AppComponent {
  originaldata = [{
    "name": "item 1",
    "id": 1,
    "price": 10
  },
  {
    "name": "item 2",
    "id": 2,
    "price": 20
  },
  {
    "name": "item 1",
    "id": 1,
    "price": 10
  },
  {
    "name": "item 3",
    "id": 3,
    "price": 30
  }]
  viewData = []

  constructor() {
    var groupedByData = this.groupByKey(this.originaldata, 'name')

    (Object.keys(groupedByData)).forEach(x => {
      this.viewData.push(
        {
          name:x,
          quantity : groupedByData[x].length + 'x',
          subtotal :  (groupedByData[x].map(x=> x.price)).reduce(function(a, b) { return a + b; }, 0)
        }
      )
    })
    console.log(this.viewData)
  }

  groupByKey(data, key) {
    return data.reduce(function (rv, x) {
      (rv[x[key]] = rv[x[key]] || []).push(x);
      return rv;
    }, {});
  };
}

Template

<table>
    <tr *ngFor="let item of viewData">
    <td>{{item.quantity}}</td>
    <td>{{item.name}}, </td>
    <td>subtotal  {{item.subtotal}}</td>
    </tr>
</table>

See Stackbiltz Demo

Adrita Sharma
  • 21,581
  • 10
  • 69
  • 79