web-dev-qa-db-fra.com

Table angulaire des matières rowspan colonnes basées sur la taille de la propriété du tableau d'objets dataSource

Même maintenant, dans la version 7.2 de Angular Material, je n'arrive pas à trouver des exemples d'utilisation de rowspan sur mat-table et de conserver les fonctionnalités du composant.

C'est à quelle distance (courte?) J'ai:

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

L'exemple ci-dessus dans le Stackblitz est "presque" ce que je recherche, mais je ne suis pas en mesure de voir comment le terminer.

...
===============================================
||     ||            ||            ||  row1  ||
||  1  ||  Hydrogen  ||   1.0079   ||========||
||     ||            ||            ||  row2  ||
===============================================
||     ||            ||            ||  row1  ||
||     ||            ||            ||========||
||  2  ||   Helium   ||   4.0026   ||  row2  ||
||     ||            ||            ||========||
||     ||            ||            ||  row3  ||
===============================================
||     ||            ||            ||  row1  ||
||  3  ||  Lithium   ||   6.941    ||========||
||     ||            ||            ||  row2  ||
===============================================
...

Vous trouverez un exemple utilisant un autre format de métadonnées dans:

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

Après mon Stackblitz (le premier lien), mes questions sont les suivantes:

Est-ce que je suis trop loin de ce résultat?

Comment puis-je boucler les lignes en fonction de la longueur de la taille des lignes ['descriptions']?

Et si j'avais une autre propriété de tableau à l'intérieur de l'objet? Puis-je itérer et générer les colonnes/rangées/rangspan avec sa taille, afin qu'il devienne plus générique?

J'essaie de trouver une solution générique pour la communauté.

6
Barni

Eh bien, il semble que la table material n’ait pas de documentation api pour cela, je n’ai trouvé aucune astuce pour le faire aussi, mais nous pouvons modifier les données pour appuyer ceci, selon votre deuxième exemple, nous pouvons reformer les données en un nouveau fichier. nous pouvons obtenir notre résultat attendu.

Étape 1 :

    const originalData = [
      { id: 1, name: 'Hydrogen', weight: 1.0079, descriptions: ['row1', 'row2'] },
      { id: 2, name: 'Helium', weight: 4.0026, descriptions: ['row1', 'row2', 'row3'] },
      { id: 3, name: 'Lithium', weight: 6.941, descriptions: ['row1', 'row2'] },
      { id: 4, name: 'Beryllium', weight: 9.0122, descriptions: ['row1', 'row2', 'row3'] },
      { id: 5, name: 'Boron', weight: 10.811, descriptions: ['row1'] },
      { id: 6, name: 'Carbon', weight: 12.0107, descriptions: ['row1', 'row2', 'row3'] },
      { id: 7, name: 'Nitrogen', weight: 14.0067, descriptions: ['row1'] },
      { id: 8, name: 'Oxygen', weight: 15.9994, descriptions: ['row1'] },
      { id: 9, name: 'Fluorine', weight: 18.9984, descriptions: ['row1', 'row2', 'row3'] },
      { id: 10, name: 'Neon', weight: 20.1797, descriptions: ['row1', 'row2', 'row3'] },
    ]; //original data

    const DATA = originalData.reduce((current, next) => {
      next.descriptions.forEach(b => {
        current.Push({ id: next.id, name: next.name, weight: next.weight, descriptions: b })
      });
      return current;
    }, []);//iterating over each one and adding as the description 
    console.log(DATA)

    const ELEMENT_DATA: PeriodicElement[] = DATA; //adding data to the element data

Étape 2

ce sera comme il est en tant que votre deuxième lien stackblitz.

 getRowSpan(col, index) {    
    return this.spans[index] && this.spans[index][col];
  }

Étape 3

comme c'est par votre deuxième lien

  constructor() {
    this.cacheSpan('Priority', d => d.id);
    this.cacheSpan('Name', d => d.name);
    this.cacheSpan('Weight', d => d.weight);
  }

  /**
   * Evaluated and store an evaluation of the rowspan for each row.
   * The key determines the column it affects, and the accessor determines the
   * value that should be checked for spanning.
   */
  cacheSpan(key, accessor) {
    for (let i = 0; i < DATA.length;) {
      let currentValue = accessor(DATA[i]);
      let count = 1;

      // Iterate through the remaining rows to see how many match
      // the current value as retrieved through the accessor.
      for (let j = i + 1; j < DATA.length; j++) {
        if (currentValue != accessor(DATA[j])) {
          break;
        }

        count++;
      }

      if (!this.spans[i]) {
        this.spans[i] = {};
      }

      // Store the number of similar values that were found (the span)
      // and skip i to the next unique row.
      this.spans[i][key] = count;
      i += count;
    }
  }

Étape 4

Utilisation de l'index pour transmettre à rowspan et masquer les lignes là où il n'est pas nécessaire

    <ng-container matColumnDef="id">
        <th mat-header-cell *matHeaderCellDef> Priority </th>
        <td mat-cell *matCellDef="let data;let i = dataIndex" [attr.rowspan]="getRowSpan('Priority',i)" [style.display]="getRowSpan('Priority', i) ? '' : 'none'">
         {{ data.id }} </td>
    </ng-container>

    <ng-container matColumnDef="name">
        <th mat-header-cell *matHeaderCellDef> Name </th>
        <td mat-cell *matCellDef="let data;let i = dataIndex" [attr.rowspan]="getRowSpan('Name',i)" [style.display]="getRowSpan('Name', i) ? '' : 'none'">
         {{ data.name }} </td>
    </ng-container>

    <ng-container matColumnDef="weight">
        <th mat-header-cell *matHeaderCellDef> Weight </th>
        <td mat-cell *matCellDef="let data;let i = dataIndex" [attr.rowspan]="getRowSpan('Weight',i)" [style.display]="getRowSpan('Weight', i) ? '' : 'none'">
         {{ data.weight }} </td>
    </ng-container>

    <ng-container matColumnDef="descriptions">
        <th mat-header-cell *matHeaderCellDef> Descriptions </th>
        <td mat-cell *matCellDef="let data"> {{ data.descriptions }} </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> 


</table>

Voici la démo

3
Just code

Nous devons dire combien de lignes il y a, mais certaines lignes ont le même id et nous trierons et fusionnerons td si elles utilisaient le même identifiant . Pour cette raison, JS ne peut pas savoir combien de <tr> devrait être là.

Deux façons pour vous: 1- Formatez vos données, conservez une description par ligne, comme dans l'exemple suivant: href second, [{id, name, weight, countdescriptions, description},...], et utilisez [attr.rowspan]='data.countdescriptions' à la place de [attr.rowspan]='getRowSpan(data.id)'. 2- Mettez à jour le format du contenu, comme <ul><li *ngFor... dans Description <td> et supprimez l'attribut [attr.rowspan].

1
Nick Wang