4
votes

Données de regroupement angulaire 7 à l'aide de * ngfor

Pour le moment, des données arrivent comme celles-ci dans mon application angulaire

https://stackblitz.com/edit/angular-ymmt4d

 entrez la description de l'image ici

Comment Je groupe et classe les données par État et par comté et affichez comme ci-dessous le tableau

 entrez la description de l'image ici

 <table >
        <tr>
          <th>State</th>
          <th>County</th>
          <th>Item</th>
        </tr>
        <ng-container *ngFor="let dataitem of data">
        <tr>
          <td>{{dataitem.state}}</td>
          <td>{{dataitem.county}}</td>
          <td>{{dataitem.item}}</td>
        </tr>
        </ng-container>
    </table>
import { Component } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  data = [
    { state: 'MN', county: '1', item: 0.297 },
    { state: 'MN', county: '1', item: 0.04 },
      { state: 'CA', county: '2', item: 0.019 },
    { state: 'MN', county: '1', item: 0.0374 }, 
    { state: 'CA', county: '2', item: 0.037 }
]
}


3 commentaires

est-il possible pour vous de changer le format des données pour qu'il soit comme {état: 'MN', comté: '1', élément; [0.297,0.04,0.0374]}?


Je ne pense pas pouvoir changer le format des données


competa.com/blog/custom-groupby-pipe-angular-4


5 Réponses :


1
votes

En utilisant cette réponse comme un guide, vous pouvez nettoyer vos données à l'avance (ou utiliser un tube) pour créer des objets imbriqués.

Quelque chose dans le sens de (tiré grossièrement de l'exemple lié)

<div *ngFor="let item of list; let i = index;">
  <div *ngIf="i > 0 && item.state !== list[i-1].state">{{item.state}}</div>
</div>

devrait produire quelque chose de similaire à

data = [
    { 'MN': [
        { county: '1', item: 0.297 }
        ....
    ]}
]

Vous pouvez également utiliser la logique fancy * ngIf et index si votre liste est triée. En savoir plus ici . Quelque chose du genre:

key = 'state';
data = data.reduce((data, x) => {
    (data[x[key]] = data[x[key]] || []).push(x);
    return data;
  }, {});


0 commentaires

1
votes

transformez vos données en plusieurs tableaux à l'aide de lodash.

https://lodash.com /docs/4.17.11#groupBy

<tbody *ngFor="let state of states">...</tbody>

dans votre table, vous pouvez avoir plusieurs tbodies

import { groupBy } from 'lodash-es'
const states = groupBy(data, 'state')

p >


0 commentaires

3
votes

si vous avez les données ordonnées, vous pouvez utiliser let i = index et vérifier si les données avant sont eauql en utilisant un opérateur conditionnel

<ng-container *ngFor="let dataitem of data;let i=index">
<tr>
  <td>{{i>0 && data[i-1].state==dataitem.state?'':dataitem.state}}</td>
  <td>{{i>0 && data[i-1].county==dataitem.county?'':dataitem.county}}</td>
  <td>{{dataitem.item}}</td>
</tr>
</ng-container>


0 commentaires

1
votes

Voici une solution entièrement fonctionnelle avec un Stackblitz Démo avec fusion de cellules similaires .

Vous devez calculer une longueur de lignes pour chaque élément et la lier à l'attribut rowspan du td . Vous devez également rendre conditionnellement le td pour l'afficher uniquement pour le premier élément de chaque état.

Pour cela, vous pouvez créer un tableau prétraité, trié par état et par comté , avec des propriétés span ajoutées pour les états et les comtés.

Pour définir les propriétés span , vous pouvez compter le nombre d'enfants pour chaque état et chaque comté pour l'état en filtrant le tableau d'origine.

Le but est d'obtenir un tableau comme celui-ci:

export class AppComponent  {
  data = [
    { state: 'MN', county: '1', item: 0.297 },
    { state: 'MN', county: '1', item: 0.04 },
    { state: 'MN', county: '3', item: 0.14 },
    { state: 'CA', county: '2', item: 0.019 },
    { state: 'MN', county: '1', item: 0.0374 }, 
    { state: 'CA', county: '2', item: 0.037 },
    { state: 'CA', county: '3', item: 0.14 }
  ];

  dataExt: any[] = [];

  constructor() {
    this.processData();
  }

  private processData() {
    const statesSeen = {};
    const countiesSeen = {};

    this.dataExt = this.data.sort((a, b) => {
      const stateComp = a.state.localeCompare(b.state);
      return stateComp ? stateComp : a.county.localeCompare(b.county);
    }).map(x => {
      const stateSpan = statesSeen[x.state] ? 0 :
        this.data.filter(y => y.state === x.state).length;

      statesSeen[x.state] = true;

      const countySpan = countiesSeen[x.state] && countiesSeen[x.state][x.county] ? 0 :
        this.data.filter(y => y.state === x.state && y.county === x.county).length;

      countiesSeen[x.state] = countiesSeen[x.state] || {};
      countiesSeen[x.state][x.county] = true;

      return { ...x, stateSpan, countySpan };
    });
  }
}

Voici le code:

 <table>
    <tr>
      <th>State</th>
      <th>County</th>
      <th>Item</th>
    </tr>
    <tr *ngFor="let item of dataExt">
      <td [attr.rowspan]="item.stateSpan" *ngIf="item.stateSpan">{{ item.state }}</td>
      <td [attr.rowspan]="item.countySpan" *ngIf="item.countySpan">{{ item.county }}</td>
      <td>{{ item.item }}</td>
    </tr>
</table>
[
  {state: "CA", county: "2", item: 0.019, stateSpan: 3, countySpan: 2},
  {state: "CA", county: "2", item: 0.037, stateSpan: 0, countySpan: 0},
  {state: "CA", county: "3", item: 0.14, stateSpan: 0, countySpan: 1},
  {state: "MN", county: "1", item: 0.297, stateSpan: 4, countySpan: 3},
  {state: "MN", county: "1", item: 0.04, stateSpan: 0, countySpan: 0},
  {state: "MN", county: "1", item: 0.0374, stateSpan: 0, countySpan: 0},
  {state: "MN", county: "3", item: 0.14, stateSpan: 0, countySpan: 1}
]

Voici le tableau résultant:

 entrez la description de l'image ici

blockquote>

0 commentaires

0
votes

Peut-être quelque chose comme ceci:

[
  { state: 'CA', county: '2', item: 0.019 },
  { item: 0.037 },
  { state: 'MN', county: '1', item: 0.297 },
  ...
]

Cela devrait être une complexité O (log n) et le résultat ressemblera à ceci:

interface Item {
  state?: string;
  county?: string;
  item: number;
}

private processData(data: any[]): Item[] {
  // Sort alphabetically
  const sorted = data.sort((a, b) => {
    if(a.state < b.state) { return -1; }
    if(a.state > b.state) { return 1; }
    return 0;
  });

  // Return original object if state value is different to
  // previous object (or if first iteration). Otherwise
  // return object with sole `item` property.
  return sorted.map((el, i) => {
    if (i === 0 || sorted[i-1].state !== el.state) {
      return el;
    } else {
      return {
        item: el.item
      };
    }
  });
}


0 commentaires