igx-grid で列をグループ化する際、同じ値でも行データの他の項目によってグループを分けたい場合は、groupingComparersortStrategy を組み合わせてグループ化ロジックをカスタマイズします。

顧客列のグループ化における課題

例えば、以下のような受注データがあるとします。

この状態で顧客列をグループ化すると、次のように表示されます。

地域が「関東」の「さくら商事株式会社」と「近畿」の「さくら商事株式会社」は別会社ですが、標準のグループ化では同一グループとして扱われてしまいます。

igx-grid の設定

この課題を解決するため、igx-gridgroupingExpressions を設定し、対象の顧客列に groupingComparersortStrategy を割り当てます。

<igx-grid [data]="data()" [groupingExpressions]="groupingExpressions">
  <igx-column field="orderId" header="注文ID"></igx-column>
  <igx-column
    field="customer"
    header="顧客"
    [groupable]="true"
    [groupingComparer]="customerGroupingComparer"
    [sortStrategy]="customerSortStrategy"
  ></igx-column>
  <igx-column field="region" header="地域"></igx-column>
  <igx-column field="amount" header="金額" ...></igx-column>
</igx-grid>

groupingComparer と sortStrategy の使用

まず sortStrategy には DefaultSortingStrategy を拡張したクラスを指定します。customer を第一キー、region を第二キーとして事前ソートすることで、同じ顧客・地域の行を必ず隣接させ、グループ化の前提となる並び順を保証します。

class CustomerRegionSortingStrategy extends DefaultSortingStrategy {
  public override sort(
    data: SalesOrder[],
    fieldName: string,
    dir: SortingDirection,
    _ignoreCase: boolean,
    valueResolver: (obj: any, key: string, isDate?: boolean) => any,
    isDate?: boolean,
  ): SalesOrder[] {
    const reverse = dir === SortingDirection.Desc ? -1 : 1;
    return [...data].sort((a, b) => {
      const customerCompare =
        reverse * this.compareValues(valueResolver(a, fieldName, isDate), valueResolver(b, fieldName, isDate));
      return customerCompare !== 0 ? customerCompare : reverse * this.compareValues(a.region, b.region);
    });
  }
}

protected readonly customerSortStrategy = CustomerRegionSortingStrategy.instance();

protected readonly groupingExpressions = [
  {
    fieldName: 'customer',
    dir: SortingDirection.Asc,
    ignoreCase: true,
    strategy: this.customerSortStrategy,
  },
];

次に groupingComparer には、コールバックの第3・第4引数(行データ全体)を使って比較する Comparer 関数を指定します。顧客名が一致していても region が異なれば別グループとして扱うことで、グループを分割しています。

// 第3・第4引数(行データ全体)で region を比較してグループを分ける
protected readonly customerGroupingComparer = (
  a: string,
  b: string,
  currRec?: SalesOrder,
  groupRec?: SalesOrder,
): number => {
  if (a !== b) {
    return -1;
  }
  return currRec?.region === groupRec?.region ? 0 : -1;
};

実行結果

顧客列でグループ化すると、同じ「さくら商事株式会社」でも地域(関東 / 近畿)が異なるため、別々のグループとして表示されるようになります。

Tagged:

製品について

Ignite UI for Angular