igx-grid で列をグループ化する際、同じ値でも行データの他の項目によってグループを分けたい場合は、groupingComparer と sortStrategy を組み合わせてグループ化ロジックをカスタマイズします。
顧客列のグループ化における課題
例えば、以下のような受注データがあるとします。

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

地域が「関東」の「さくら商事株式会社」と「近畿」の「さくら商事株式会社」は別会社ですが、標準のグループ化では同一グループとして扱われてしまいます。
igx-grid の設定
この課題を解決するため、igx-grid に groupingExpressions を設定し、対象の顧客列に groupingComparer と sortStrategy を割り当てます。
<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;
};
実行結果
顧客列でグループ化すると、同じ「さくら商事株式会社」でも地域(関東 / 近畿)が異なるため、別々のグループとして表示されるようになります。
