web-dev-qa-db-fra.com

Angular Groupe de lignes de la table de tapis

En laissant de côté les bibliothèques qui fournissent le groupement de lignes pour leurs tables particulières, j'essaie d'implémenter une telle fonctionnalité sur Matière angulaire de Matière angulaire 2 qui ne vient pas avec une telle fonctionnalité.

Articles à remplir la table:

export class BasketItem{
    public id: number;
    public position: number;
    public quantity: number;
    public groupId: number;
} 

Regroupement de lignes ayant la même propriété groupId dans le tableau suivant

 <mat-table class="mat-elevation-z8" [dataSource]="dataSource" multiTemplateDataRows matSort matSortActive="position" matSortDirection="asc" matSortDisableClear >

      <!-- Position Column -->  
      <ng-container matColumnDef="position">
        <mat-header-cell *matHeaderCellDef mat-sort-header>
          <b>Position</b>
        </mat-header-cell>
        <mat-cell *matCellDef="let basketItem">{{basketItem.position}}</mat-cell>
      </ng-container>

      <!-- Quantity Column -->
      <ng-container matColumnDef="quantity">
        <mat-header-cell *matHeaderCellDef>
          <b>Quantity</b>
        </mat-header-cell>
         <mat-cell *matCellDef="let basketItem">{{basketItem.quantity}}</mat-cell>
      </ng-container>

      <!-- GroupId Column -->  
      <ng-container matColumnDef="position">
        <mat-header-cell *matHeaderCellDef mat-sort-header>
          <b>GroupId </b>
        </mat-header-cell>
        <mat-cell *matCellDef="let basketItem">{{basketItem.GroupId }}</mat-cell>
      </ng-container>


      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>

      <mat-row *matRowDef="let basketItem; columns: displayedColumns;" (click)="onSelect(basketItem)"></mat-row>

    </mat-table>

Des idées sur la façon dont le groupe de lignes pourrait être abordé?

10
Vlad Danila

Une réponse très simple serait de trier par GroupID, cela mettra ces lignes ensemble dans des groupes. Cependant, je suppose que vous voulez une ligne d’en-tête affichée avant chaque groupe.

Vous pouvez fournir une alternative <mat-row *matRowDef="... qui utilise une clause where. Ceci peut être utilisé pour afficher un ensemble de colonnes différent de celui par défaut. La clause where prend une fonction qui retourne true si ce matRowDef doit être utilisé.

Les données que vous fournissez à la table sont alors les lignes de données entrecoupées de lignes de groupe, et la fonction les indique les unes aux autres. Prise Utilisation de base de <table mat-table> _ En tant que démarreur, ajoutez manuellement les groupes et ajoutez la fonction de clause where à app/table-basic-example.ts:

    import {Component} from '@angular/core';

    export interface PeriodicElement {
      name: string;
      position: number;
      weight: number;
      symbol: string;
    }

    export interface Group {
      group: string;
    }

    const ELEMENT_DATA: (PeriodicElement | Group)[] = [
      {group: "Group 1"},
      {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
      {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
      {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
      {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
      {group: "Group 2"},
      {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
      {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
      {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
      {group: "Group 3"},
      {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
      {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
      {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
    ];

    /**
     * @title Basic use of `<table mat-table>`
     */
    @Component({
      selector: 'table-basic-example',
      styleUrls: ['table-basic-example.css'],
      templateUrl: 'table-basic-example.html',
    })
    export class TableBasicExample {
      displayedColumns: string[] = ['position', 'name', 'weight', 'symbol'];
      dataSource = ELEMENT_DATA;

      isGroup(index, item): boolean{
        return item.group;
      }
    }


    /**  Copyright 2018 Google Inc. All Rights Reserved.
        Use of this source code is governed by an MIT-style license that
        can be found in the LICENSE file at http://angular.io/license */

Et ajoutez la colonne groupHeader et l'extra matRowDef à app/table-basic-example.html:

    <mat-table [dataSource]="dataSource" class="mat-elevation-z8">

      <!--- Note that these columns can be defined in any order.
            The actual rendered columns are set as a property on the row definition" -->

      <!-- Position Column -->
      <ng-container matColumnDef="position">
        <mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
      </ng-container>

      <!-- Name Column -->
      <ng-container matColumnDef="name">
        <mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
      </ng-container>

      <!-- Weight Column -->
      <ng-container matColumnDef="weight">
        <mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
      </ng-container>

      <!-- Symbol Column -->
      <ng-container matColumnDef="symbol">
        <mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
        <mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
      </ng-container>

      <ng-container matColumnDef="groupHeader">
        <mat-cell *matCellDef="let group">{{group.group}}</mat-cell>
      </ng-container>

      <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
      <mat-row *matRowDef="let row; columns: ['groupHeader']; when: isGroup"> </mat-row>

    </mat-table>



    <!-- Copyright 2018 Google Inc. All Rights Reserved.
        Use of this source code is governed by an MIT-style license that
        can be found in the LICENSE file at http://angular.io/license -->

Voici un stackblitz fini qui se groupe par la lettre initiale de l'élément.

Et voici un stackblitz beaucoup plus développé , il vous suffit de fournir la liste des colonnes que vous souhaitez grouper et il insérera les lignes du groupe à votre place. Vous pouvez également cliquer sur les lignes du groupe pour les développer ou les réduire.

Et enfin, voici un projet Github qui modifie une copie de la classe MatTableDataSource à partir de la base de code de matériau. Fonctionne bien avec les filtres et les tris, mais "rivalise" avec le paginateur car ils limitent la vue des enregistrements de différentes manières.

23
Stephen Turner

En utilisant la réponse de Stephen Turner, partageant maintenant ceci stackblitz fork

  • Dynamicaly découvre des colonnes dans les données fournies
  • Permet de grouper par valeurs distinctes des colonnes à la demande

Comme il a été souligné plus tôt dans ce fil,

le moyen facile de groupBy avec Mat-Table est en pratique d'ajouter des lignes dans les données affichées,

ces lignes ajoutées au début de chaque nouveau groupe peuvent recevoir un modèle personnalisé avec le @Input (matRowDefWhen)

<!-- Default Table lines -->
<tr mat-header-row *matHeaderRowDef="displayedColumns; sticky: true"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

<!-- Group line -->
<tr mat-row *matRowDef="let row; columns: ['groupName']; when: isAGroup"></tr>

Dans l'exemple ci-dessus, la fonction isAGroup doit renvoyer true lorsqu'une ligne est un groupe et ne fait pas partie des données initiales.

De plus, le modèle de colonne nom de groupe pourrait être implémenté comme suit

<ng-container matColumnDef="groupName">
    <td colspan="999" mat-cell *matCellDef="let group">
      {{group.name}}
    </td>
</ng-container>

Enfin, si votre jeu de données peut varier, vous pouvez ajouter une boucle sur les définitions de modèle de colonne.

<ng-container *ngFor="let col of displayedColumns" [matColumnDef]="col">
    <th mat-header-cell *matHeaderCellDef>{{ col }}</th>
    <td mat-cell *matCellDef="let row">{{ row[col] }}</td>
</ng-container>

ensuite, masquer et afficher les lignes du groupe consiste simplement à filtrer les données affichées en fonction des nouveaux critères de groupe masqués et à actualiser les données affichées.

Désolé pour ce fil necro, visant uniquement à partager un morceau de code réutilisable à ceux qui recherchent une solution.

2