Pour le moment, des données arrivent comme celles-ci dans mon application angulaire
https://stackblitz.com/edit/angular-ymmt4d
Comment Je groupe et classe les données par État et par comté et affichez comme ci-dessous le tableau
<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 }
]
}
5 Réponses :
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;
}, {});
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 >
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>
Voici une solution entièrement fonctionnelle avec un Stackblitz Démo avec fusion de cellules similaires .
Vous devez calculer une
longueur de lignespour chaque élément et la lier à l'attributrowspandutd. Vous devez également rendre conditionnellement letdpour 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
spanajouté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:
blockquote>
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
};
}
});
}
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