簡體   English   中英

Angular Material mat-table 行分組

[英]Angular Material mat-table Row Grouping

撇開為其特定表提供行分組的庫不談,我正在嘗試在Angular Material 2 mat-table上實現這樣一個功能,它沒有這樣一個功能。

填充表格的項目:

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

對下表中具有相同groupId屬性的行進行分組

 <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>

關於如何處理行分組的任何想法?

一個非常簡單的答案是按 GroupID 排序,這會將這些行放在一起。 但是,我猜您希望在每個組之前顯示一個標題行。

您可以提供一個替代<mat-row *matRowDef="...使用 where 子句。這可用於顯示一組非默認的列。 where 子句采用一個函數,如果 matRowDef 應該是,則該函數返回 true用過的。

您提供給表的數據將是散布在組行中的數據行,並且該函數會相互區分。 <table mat-table> Basic使用為開端,手動添加組,在app/table-basic-example.ts中添加where子句函數:

    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 */

並將 groupHeader Column 和額外的 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 -->

這是一個完成的stackblitz ,它按元素的首字母分組。

這是一個更加發達的stackblitz,只需提供您想要分組的列列表,它就會為您插入組行。 您還可以單擊組行以展開或折疊它們

最后是一個Github 項目,它修改了材料代碼庫中的 MatTableDataSource 類的副本。 與過濾器和排序一起工作得很好,但與分頁器“競爭”,因為它們都以不同的方式限制記錄的視圖。

使用 Stephen Turner 的回答,現在分享這個stackblitz fork

  • 動態發現給定數據中的列
  • 允許根據需要對列的不同值進行分組

正如本主題前面所指出的那樣,

使用 Mat-Table 進行 groupBy 的簡單方法實際上是在顯示的數據中添加行,

在每個新組開始時添加的這些行可以使用@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>

在上面的例子中,當一行是一個組而不是初始數據的一部分時,isAGroup 函數應該返回 true。

也可以按如下方式實現 groupName 列模板

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

最后,如果您的數據集可以變化,可以在列模板定義上添加一個循環

<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>

然后隱藏和顯示組的行只是根據新隱藏的組標准過濾顯示的數據並刷新顯示的數據。

很抱歉這個線程 necro,只是為了向那些尋找解決方案的人分享一段可重用的代碼。

您甚至可以通過像這樣解析編譯和分組過程來進一步分解它:

  sortStringArray(array: string[], sortOrder: string = 'asc'): string[] {
    if(sortOrder === 'asc'){
      array.sort((a: string, b: string) => a > b ? 1 : a < b ? -1 : 0);
    }
    else if(sortOrder === 'desc'){
      array.sort((a: string, b: string) => a > b ? -1 : a < b ? 1 : 0);
    }
    return array;
  }

  groupStringArray(array: string[], sortOrder: string = 'asc'): string[] {
    let sortedArray = this.sortStringArray(array, sortOrder);
    let groupHeader = '';
    let groupedArray = [];

    for(let i = 0; i < sortedArray.length; i++){
      if(groupHeader !== sortedArray[i]){
        groupHeader = sortedArray[i];
        groupedArray.push({ isGroup: true, value: groupHeader });
        groupedArray.push(sortedArray[i]);
      }
      else{
        groupedArray.push(sortedArray[i]);
      }
    }

    return groupedArray;
  }

...並針對您正在處理的每種不同類型的值以及您希望與字段一起返回的內容執行此操作。 這對於您可以在其他地方應用這些函數並在表的分組中輕松實現它們的可讀性和單一責任要高得多。 我已將我的設置設置為處理所有類型,甚至以這種清晰的可讀性遞歸工作。 當您 1) 意識到首先排序可以更容易地查找和設置分組值時,問題更容易解決,2) 分組只是意識到參考值不再恆定的地方。 這是一種蠻力方法,但它基本上是分組邏輯所需要的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM