Angular Grid グループ化
Ignite UI for Angular Table または UI Grid の Group By 動作は、列の値に基づいてグループ化されたデータ行を作成します。igxGrid
の Group By では、グループを階層構造で視覚化できます。グループデータ行は展開または縮小でき、グループの順序は UI または API で変更できます。行選択を有効にすると、Group By 行セレクターがグループ行の一番左の領域に描画されます。rowSelection
プロパティが単一に設定されている場合、チェックボックスは無効になり、選択が行われるグループの表示としてのみ機能します。rowSelection
プロパティが複数に設定されている場合、Group By 行セレクターをクリックすると、このグループに属するすべてのレコードが選択されます。
Angular Grid グループ化の例
この例は、大量のデータのグループ化が可能であることを示しています。列ヘッダーを一番上 (グループ化領域) にドラッグすると、ユーザーは選択した列のデータを階層構造で表示できます。さらに列ヘッダーを一番上にドラッグすることで、複数のフィールドでグループ化できます。これらのグループ化オプションは、ユーザーが多数の行と列を持つテーブルがあり、はるかに高速で視覚的に受け入れられる方法でデータを表示しようとする場合に役立ちます。
import { NgModule } from "@angular/core" ;
import { FormsModule } from "@angular/forms" ;
import { BrowserModule } from "@angular/platform-browser" ;
import { BrowserAnimationsModule } from "@angular/platform-browser/animations" ;
import { AppComponent } from "./app.component" ;
import {
IgxButtonModule,
IgxGridModule,
IgxSwitchModule,
IgxIconModule,
IgxBadgeModule
} from "igniteui-angular" ;
import { GridGroupBySampleComponent } from "./grid/grid-groupby-sample/grid-groupby-sample.component" ;
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
GridGroupBySampleComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxButtonModule,
IgxGridModule,
IgxIconModule,
IgxBadgeModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー import { Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core' ;
import {
DefaultSortingStrategy,
GridSelectionMode,
IgxGridComponent,
ISortingExpression,
SortingDirection
} from 'igniteui-angular' ;
import { INVOICE_DATA } from '../../data/invoiceData' ;
@Component ({
encapsulation : ViewEncapsulation.None,
selector : 'app-grid-groupby-sample' ,
styleUrls : ['./grid-groupby-sample.component.scss' ],
templateUrl : './grid-groupby-sample.component.html'
})
export class GridGroupBySampleComponent {
@ViewChild ('grid1' , { read : IgxGridComponent, static : true })
public grid1: IgxGridComponent;
public data;
public expr: ISortingExpression[];
public selectionMode: GridSelectionMode = 'multiple' ;
constructor ( ) {
this .data = INVOICE_DATA;
this .expr = [
{ dir : SortingDirection.Asc, fieldName : 'ShipCountry' , ignoreCase : false ,
strategy : DefaultSortingStrategy.instance() },
{ dir : SortingDirection.Asc, fieldName : 'ShipCity' , ignoreCase : false ,
strategy : DefaultSortingStrategy.instance() }
];
}
public formatDate (val: Date ) {
return new Intl .DateTimeFormat('en-US' ).format(val);
}
public formatCurrency (value: number ) {
return '$' + value.toFixed(2 );
}
public isDate (value: any ) {
if (value instanceof Date ) {
return true ;
} else {
return false ;
}
}
public calc2017 (values: any [] ) {
const startDate = new Date ('1/1/2017' );
const endDate = new Date ('12/31/2017' );
return values.filter((x ) => x.OrderDate >= startDate && x.OrderDate <= endDate).length;
}
}
ts コピー <div class ="grid__wrapper" >
<igx-grid [igxPreventDocumentScroll ]="true" #grid1 [data ]="data" [width ]="'100%'" [height ]="'570px'" [rowSelection ]="selectionMode" [groupingExpressions ]="expr" >
<igx-column field ="OrderID" header ="Order ID" [hidden ]="true" >
</igx-column >
<igx-column field ="ShipCountry" header ="Ship Country" width ="200px" [groupable ]="true" >
</igx-column >
<igx-column field ="OrderDate" header ="Order Date" width ="200px" [formatter ]="formatDate" [groupable ]="true" >
</igx-column >
<igx-column field ="PostalCode" header ="Postal Code" width ="200px" [groupable ]="true" >
</igx-column >
<igx-column field ="Discontinued" header ="Discontinued" width ="200px" [groupable ]="true" >
<ng-template igxCell let-cell ="cell" let-val >
<img *ngIf ="val" src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/active.png" title ="Continued" alt ="Continued" />
<img *ngIf ="!val" src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/expired.png" title ="Discontinued" alt ="Discontinued" />
</ng-template >
</igx-column >
<igx-column field ="ShipName" header ="Ship Name" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="ShipCity" header ="Ship City" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="ShipperName" header ="Shipper Name" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="Salesperson" header ="Salesperson" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="UnitPrice" header ="Unit Price" width ="150px" [formatter ]="formatCurrency" dataType ="number" [groupable ]="true" >
</igx-column >
<igx-column field ="Quantity" header ="Quantity" width ="150px" dataType ="number" [groupable ]="true" >
</igx-column >
<ng-template igxGroupByRow let-groupRow >
<div class ="igx-group-label" >
<igx-icon family ="material" class ="igx-group-label__icon" > group_work</igx-icon >
<span class ="igx-group-label__column-name" >
{{ groupRow.expression.fieldName }}:
</span >
<span class ="igx-group-label__text" > {{ isDate(groupRow.value) ? formatDate(groupRow.value) : groupRow.value }}</span >
<igx-badge [value ]="groupRow.records.length" class ='igx-group-label__count-badge' > </igx-badge >
<span style ="color:#09f;" > Ordered in 2017:</span > <span class ="igx-badge__circle igx-badge__circle--default" > {{ calc2017(groupRow.records)}}</span >
</div >
</ng-template >
</igx-grid >
</div >
html コピー .grid-controls {
display : flex;
flex-flow : column nowrap;
justify-content : space-between;
margin : 0 16px 24px ;
igx-switch {
margin-top : 24px ;
}
}
.grid__wrapper {
padding-top : 16px ;
margin : 0 16px ;
}
.header-icon {
font-size : 1.4em ;
width : 1.1em ;
height : 1.1em ;
float : right;
cursor : pointer;
}
.header {
height : 100% ;
}
.igx-grid__th .title {
width : 100% ;
cursor : auto;
}
scss コピー
このサンプルが気に入りましたか? 完全な Ignite UI for Angularツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。
初期のグループ化状態
グリッドの groupingExpressions
プロパティに式の配列を割り当てることによって、グリッドの初期グループ化を定義することができます。
public ngOnInit ( ) {
grid.groupingExpressions = [
{ fieldName : 'ProductName' , dir : SortingDirection.Desc },
{ fieldName : 'Released' , dir : SortingDirection.Desc }
];
}
typescript
グループ式は、ISortingExpression
インターフェイスを実装します。
Group By API
グループ化 API
グループ化は、UI およびグリッド コンポーネントで公開された API で実行できます。各列の groupable
プロパティを true
に設定してエンドユーザーは特定の列でグリッド データをグループ化できます。
<igx-grid [data ]="data" >
<igx-column *ngFor ="let c of columns" [field ]="c.field" [groupable ]="true" >
</igx-column >
</igx-grid >
html
public ngOnInit ( ) {
grid.columns.forEach((column ) => {
column.groupable = true ;
});
}
typescript
ランタイムの式は groupingExpressions
プロパティの取得または設定できます。既存の式を追加または変更する必要がある場合、ISortingExpression
の単一または配列の groupBy
メソッドを使用してください。
grid.groupBy({ fieldName : 'ProductName' , dir : SortingDirection.Desc, ignoreCase : true });
typescript
これまで、グループ化 / ソートは互いに連携して機能していました。13.2 バージョンでは、グループ化をソートから切り離す新しい動作が導入されています。たとえば、グループ化をクリアしても、グリッド内のソート式はクリアされません。その逆も同様です。それでも、列がソートおよびグループ化されている場合は、グループ化された式が優先されます。
API の展開/縮小
グループ式の他にグループ行の展開も制御できます。igxGrid
コンポーネント groupingExpansionState
の別のプロパティに保存されます。グループ行は、作成されたフィールド名とグループ化の各レベルを表す値に基づいて識別されます。以下は展開状態のインターフェイスのシグネチャです。
export interface IGroupByKey {
fieldName : string ;
value: any ;
}
export interface IGroupByExpandState {
hierarchy : Array <IGroupByKey>;
expanded: boolean ;
}
typescript
groupingExpressions
で IGroupByExpandState
のリストを直接 groupingExpansionState
に設定すると展開が変更されます。igxGrid
はグループ レコード インスタンスでトグルするメソッドを公開します。
const groupRow = this .grid.groupsRecords.find(r => r.value === "France" );
const groupRow = this .grid.getRowByIndex(0 ).groupRow;
grid.toggleGroup(groupRow);
groupRow.expanded = false ;
typescript
グループは展開済み (デフォルト ) または縮小済みに作成でき、展開状態は一般的にデフォルト動作の反対の状態のみ含みます。グループを作成して展開するかどうか、または groupsExpanded
プロパティを介すかどうかを制御できます。
グループ API ですべての行を選択/選択解除
グループ内のすべての行の選択/選択解除は、selectRowsInGroup
および deselectRowsInGroup
API メソッドを介して利用できます。
以下のコードスニペットは、グループ レコード selectRowsInGroup
メソッドを使用してグループ内のすべての行を選択するために使用できます。さらに、このメソッドの 2 番目のパラメーターは boolean プロパティです。それを使用して、前の行の選択をクリアするかどうかを選択できます。以前の選択はデフォルトで保存されます。
const groupRow = this .grid.groupsRecords.find(r => r.value === "France" );
const groupRow = this .grid.getRowByIndex(0 ).groupRow;
grid.selectRowsInGroup(groupRow);
typescript
プログラムでグループ内のすべての行の選択を解除する必要がある場合は、deselectRowsInGroup
メソッドを使用できます。
const groupRow = this .grid.groupsRecords.find(r => r.value === "France" );
const groupRow = this .grid.getRowByIndex(0 ).groupRow;
grid.deselectRowsInGroup(groupRow);
typescript
テンプレート
グループ行テンプレート
展開/縮小 UI を除くグループ行は完全にテンプレート化可能です。デフォルトでグループ アイコンを描画し、フィールド名と値を表示します。テンプレートが描画されるレコードのグループ化には、以下のシグネチャがあります:
export interface IGroupByRecord {
expression : ISortingExpression;
level: number ;
records: GroupedRecords;
value: any ;
groupParent: IGroupByRecord;
groups?: IGroupByRecord[];
}
typescript
たとえば、以下のテンプレートはグループ行集計でより詳細な情報を表示します:
<ng-template igxGroupByRow let-groupRow >
<span > Total items with value: {{ groupRow.value }} are {{ groupRow.records.length }}</span >
</ng-template >
html
グループ行セレクター テンプレート
上記のように、展開/縮小 UI を除くグループ行は完全にテンプレート化可能です。グリッド内にカスタムの GroupBy 行セレクター テンプレートを作成するには、igxGroupByRowSelector
ディレクティブを使用して <ng-template>
を宣言します。テンプレートから、Group By 行の状態に関する情報を提供するプロパティを使用して、暗黙的に提供されたコンテキスト変数にアクセスできます。
selectedCount
プロパティは、現在選択されているグループ レコードの数を示し、totalCount
はグループに属するレコードの数を示します。
<ng-template igxGroupByRowSelector let-groupByRowContext >
{{ groupByRowContext.selectedCount }} / {{ groupByRowContext.totalCount }}
</ng-template >
html
groupRow
プロパティは、グループ行への参照を返します。
<ng-template igxGroupByRowSelector let-groupByRowContext >
<div (click )="handleGroupByRowSelectorClick($event, groupByRowContext.groupRow)" > Handle groupRow</div >
</ng-template >
html
selectedCount
と totalCount
プロパティを使用して、Group By 行セレクターをチェックするか不確定にする (部分的に選択する) かを決定できます。
<igx-grid #grid [data ]="gridData" primaryKey ="ProductID" rowSelection ="multiple" >
<ng-template igxGroupByRowSelector let-context >
<igx-checkbox
[checked ]=" context.selectedCount > 0 && context.selectedCount === context.totalCount"
[indeterminate ]="context.selectedCount > 0 && context.selectedCount !== context.totalCount" >
</igx-checkbox >
</ng-template >
</igx-grid >
html
Angular Grid ページングでグループ化
グループ行は、データ行とともにページング プロセスに関係します。それらは各ページのページ サイズにカウントされます。折りたたまれた行はページング プロセスに含まれません。展開または折りたたみ操作を行うと、ページングでページ数が再計算され、必要に応じてページ インデックスが調整されます。
複数のページにまたがるグループは、ページ間で分割されます。グループ行は、開始ページでのみ表示され、後続のページでは繰り返されません。グループ行の要約情報はグループ全体に基づいて計算され、ページングの影響を受けません。
Angular ページングでグループ化の例
import { NgModule } from "@angular/core" ;
import { FormsModule } from "@angular/forms" ;
import { BrowserModule } from "@angular/platform-browser" ;
import { BrowserAnimationsModule } from "@angular/platform-browser/animations" ;
import { AppComponent } from "./app.component" ;
import {
IgxGridModule,
IgxIconModule
} from "igniteui-angular" ;
import { GridGroupByPagingSampleComponent } from "./grid/grid-group-by-paging-sample/grid-group-by-paging-sample.component" ;
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
GridGroupByPagingSampleComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxGridModule,
IgxIconModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー import { Component, ViewChild } from '@angular/core' ;
import {
DefaultSortingStrategy,
GridSelectionMode,
IgxGridComponent,
ISortingExpression,
SortingDirection
} from 'igniteui-angular' ;
import { INVOICE_DATA } from '../../data/invoiceData' ;
@Component ({
selector : 'app-grid-group-by-paging-sample' ,
templateUrl : './grid-group-by-paging-sample.component.html' ,
styleUrls : ['./grid-group-by-paging-sample.component.scss' ]
})
export class GridGroupByPagingSampleComponent {
@ViewChild ('grid1' , { read : IgxGridComponent, static : true })
public grid1: IgxGridComponent;
public data;
public expr: ISortingExpression[];
public selectionMode: GridSelectionMode = 'multiple' ;
constructor ( ) {
this .data = INVOICE_DATA;
this .expr = [
{ dir : SortingDirection.Asc, fieldName : 'ShipCountry' , ignoreCase : false ,
strategy : DefaultSortingStrategy.instance() }
];
}
public formatDate (val: Date ) {
return new Intl .DateTimeFormat('en-US' ).format(val);
}
public formatCurrency (value: number ) {
return '$' + value.toFixed(2 );
}
public isDate (value: any ) {
if (value instanceof Date ) {
return true ;
} else {
return false ;
}
}
public calc2017 (values: any [] ) {
const startDate = new Date ('1/1/2017' );
const endDate = new Date ('12/31/2017' );
return values.filter((x ) => x.OrderDate >= startDate && x.OrderDate <= endDate).length;
}
}
ts コピー <div class ="grid__wrapper" >
<igx-grid [igxPreventDocumentScroll ]="true" #grid1 [data ]="data" [width ]="'100%'" [height ]="'570px'" [rowSelection ]="selectionMode" [groupingExpressions ]="expr" >
<igx-paginator [perPage ]="10" > </igx-paginator >
<igx-column field ="ShipCountry" header ="Ship Country" width ="200px" [groupable ]="true" >
</igx-column >
<igx-column field ="ShipCity" header ="Ship City" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="UnitPrice" header ="Unit Price" width ="150px" [formatter ]="formatCurrency" dataType ="number" [groupable ]="true" >
</igx-column >
<igx-column field ="Quantity" header ="Quantity" width ="150px" dataType ="number" [groupable ]="true" >
</igx-column >
<ng-template igxGroupByRow let-groupRow >
<div class ="igx-group-label" >
<igx-icon family ="material" class ="igx-group-label__icon" > group_work</igx-icon >
<span class ="igx-group-label__column-name" >
{{ groupRow.expression.fieldName }}:
</span >
<span class ="igx-group-label__text" > {{ isDate(groupRow.value) ? formatDate(groupRow.value) : groupRow.value }}</span >
<igx-badge [value ]="groupRow.records.length" class ='igx-group-label__count-badge' > </igx-badge >
<span style ="color:#09f;" > Ordered in 2017:</span > <span class ="igx-badge__circle igx-badge__circle--default" > {{ calc2017(groupRow.records)}}</span >
</div >
</ng-template >
</igx-grid >
</div >
html コピー .grid-controls {
display : flex;
flex-flow : column nowrap;
justify-content : space-between;
margin : 0 16px 24px ;
igx-switch {
margin-top : 24px ;
}
}
.grid__wrapper {
padding-top : 16px ;
margin : 0 16px ;
}
.header-icon {
font-size : 1.4em ;
width : 1.1em ;
height : 1.1em ;
float : right;
cursor : pointer;
}
.header {
height : 100% ;
}
.igx-grid__th .title {
width : 100% ;
cursor : auto;
}
scss コピー
集計でグループ化
グループ化と要約の統合については、集計 トピックで説明しています。
キーボード ナビゲーション
グループ UI は、以下のキーボード インタラクションをサポートします。
Angular Grid カスタム グループ化
igxGrid では、列ごとまたはグループ化式ごとにカスタム グループを定義できます。これにより、カスタム条件に基づいてグループ化が提供されます。これは、複雑なオブジェクトごとにグループ化する必要がある場合、または他のアプリケーション固有のシナリオで役立ちます。
以下のサンプルは、Date
によるカスタム グループ化を示しています。日付の値は、ユーザーが選択したグループ化モードに基づいて、日、週、月、または年でソート / グループ化されています。
Angular カスタム グループ化の例
import { NgModule } from "@angular/core" ;
import { FormsModule } from "@angular/forms" ;
import { BrowserModule } from "@angular/platform-browser" ;
import { BrowserAnimationsModule } from "@angular/platform-browser/animations" ;
import { AppComponent } from "./app.component" ;
import {
IgxButtonModule,
IgxGridModule,
IgxSwitchModule,
IgxIconModule,
IgxBadgeModule
} from "igniteui-angular" ;
import { GridGroupBySampleComponent } from "./grid/grid-groupby-sample/grid-groupby-sample.component" ;
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
GridGroupBySampleComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxButtonModule,
IgxGridModule,
IgxIconModule,
IgxBadgeModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー
import { Component, ViewChild, ViewEncapsulation } from '@angular/core' ;
import {
DefaultSortingStrategy,
IgxGridComponent,
SortingDirection
} from 'igniteui-angular' ;
import { INVOICE_DATA } from '../../data/invoiceData' ;
import { DatePipe } from '@angular/common' ;
@Component ({
encapsulation : ViewEncapsulation.None,
selector : 'app-grid-groupby-custom-sample' ,
styleUrls : ['./grid-groupby-custom-sample.component.scss' ],
templateUrl : './grid-groupby-custom-sample.component.html'
})
export class GridGroupByCustomSampleComponent {
@ViewChild ('grid1' , { read : IgxGridComponent, static : true })
public grid1: IgxGridComponent;
public data;
public sortingStrategy;
public groupByOptions = [
{ name : 'Day' , ref : DaySortingStrategy.instance() },
{ name : 'Week' , ref : WeekSortingStrategy.instance() },
{ name : 'Month' , ref : BaseSortingStrategy.instance() },
{ name : 'Year' , ref : BaseSortingStrategy.instance() }
];
public groupByMode = this .groupByOptions[0 ].name;
public initialExpr;
public dateFormatter = '' ;
constructor ( ) {
this .data = INVOICE_DATA;
this .sortingStrategy = this .groupByOptions[0 ].ref;
this .dateFormatter = 'MM/dd/yyyy' ;
this .initialExpr = [
{
dir : SortingDirection.Asc,
fieldName : 'OrderDate' ,
ignoreCase : true ,
strategy : this .sortingStrategy,
groupingComparer : (a, b ) => {
const dateA = this .sortingStrategy.getParsedDate(a);
const dateB = this .sortingStrategy.getParsedDate(b);
if (this .groupByMode === 'Month' ) {
return dateA.month === dateB.month ? 0 : -1 ;
} else if (this .groupByMode === 'Year' ) {
return dateA.year === dateB.year ? 0 : -1 ;
} else if (this .groupByMode === 'Week' ) {
return this .sortingStrategy.getWeekOfDate(a) === this .sortingStrategy.getWeekOfDate(b) ? 0 : -1 ;
}
return dateA.day === dateB.day && dateA.month === dateB.month ? 0 : -1 ;
}
}
];
}
public selectionChange (event: any ) {
this .groupByMode = event.newSelection.value.name;
this .sortingStrategy = event.newSelection.value.ref;
this .dateFormatter = this .changeFormatter(this .groupByMode);
const expr = this .grid1.groupingExpressions.find(
(e ) => e.fieldName === 'OrderDate'
);
if (expr) {
expr.strategy = this .sortingStrategy;
const gexpr = this .grid1.groupingExpressions;
this .grid1.groupingExpressions = [];
this .grid1.groupingExpressions = gexpr;
}
}
public changeFormatter (mode: string ) {
if (this .groupByMode === 'Month' ) {
return 'MMMM yyyy' ;
} else if (this .groupByMode === 'Year' ) {
return 'yyyy' ;
} else if (this .groupByMode === 'Week' ){
return 'yyyy \'week\' w' ;
}
return 'MM/dd/yyyy' ;
}
public isDate (value: any ) {
if (value instanceof Date ) {
return true ;
} else {
return false ;
}
}
}
class BaseSortingStrategy extends DefaultSortingStrategy {
public getParsedDate (date: any ) {
return {
day : date.getDay(),
month : date.getMonth() + 1 ,
year : date.getFullYear()
};
}
compareValues (a: any , b: any ) {
const dateA = this .getParsedDate(a);
const dateB = this .getParsedDate(b);
return dateA.year < dateB.year ? -1 : dateA.year > dateB.year ? 1 : dateA.month < dateB.month ? -1 : dateA.month > dateB.month ? 1 : 0 ;
}
}
class DaySortingStrategy extends BaseSortingStrategy {
compareValues (a: any , b: any ) {
const dateA = this .getParsedDate(a);
const dateB = this .getParsedDate(b);
return dateA.year < dateB.year ? -1 : dateA.year > dateB.year ? 1 : dateA.month < dateB.month ? -1 : dateA.month > dateB.month ? 1 :
dateA.day < dateB.day ? -1 : dateA.day > dateB.day ? 1 : 0 ;
}
}
class WeekSortingStrategy extends BaseSortingStrategy {
public getWeekOfDate (a: any ) {
return parseInt (new DatePipe('en-US' ).transform(a, 'w' ), 10 );
}
compareValues (a: any , b: any ) {
const dateA = this .getParsedDate(a);
const dateB = this .getParsedDate(b);
const weekA = this .getWeekOfDate(a);
const weekB = this .getWeekOfDate(b);
return dateA.year < dateB.year ? -1 : dateA.year > dateB.year ? 1 : weekA < weekB ? -1 : weekA > weekB ? 1 : 0 ;
}
}
ts コピー <div class ="grid__wrapper" >
<igx-grid [igxPreventDocumentScroll ]="true" #grid1 [data ]="data" [width ]="'100%'" [height ]="'570px'" [groupingExpressions ]="initialExpr" >
<igx-grid-toolbar >
<button igxButton ="raised" [igxToggleAction ]="dropDown" [igxDropDownItemNavigation ]="dropDown" > Group By {{ groupByMode }}</button >
<igx-drop-down #dropDown (selectionChanging )="selectionChange($event)" >
<igx-drop-down-item *ngFor ="let item of groupByOptions" [value ]="item" >
{{ item.name }}
</igx-drop-down-item >
</igx-drop-down >
</igx-grid-toolbar >
<igx-column field ="OrderID" header ="Order ID" [hidden ]="true" >
</igx-column >
<igx-column field ="ShipCountry" header ="Ship Country" width ="200px" [groupable ]="true" >
</igx-column >
<igx-column field ="OrderDate" header ="Order Date" width ="200px" [groupable ]="true" dataType ="date" >
<ng-template igxCell let-value >
{{ value | date:'shortDate' }}
</ng-template >
</igx-column >
<igx-column field ="PostalCode" header ="Postal Code" width ="200px" [groupable ]="true" >
</igx-column >
<igx-column field ="Discontinued" header ="Discontinued" width ="200px" [groupable ]="true" >
<ng-template igxCell let-cell ="cell" let-val >
<img *ngIf ="val" src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/active.png" title ="Continued" alt ="Continued" />
<img *ngIf ="!val" src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/expired.png" title ="Discontinued" alt ="Discontinued" />
</ng-template >
</igx-column >
<igx-column field ="ShipName" header ="Ship Name" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="ShipCity" header ="Ship City" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="ShipperName" header ="Shipper Name" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="Salesperson" header ="Salesperson" width ="250px" [groupable ]="true" >
</igx-column >
<igx-column field ="UnitPrice" header ="Unit Price" width ="150px" dataType ="number" [groupable ]="true" >
<ng-template igxCell let-value >
{{ value | currency:'USD':'symbol-narrow'}}
</ng-template >
</igx-column >
<igx-column field ="Quantity" header ="Quantity" width ="150px" dataType ="number" [groupable ]="true" >
</igx-column >
<ng-template igxGroupByRow let-groupRow >
<div class ="igx-group-label" >
<igx-icon family ="material" class ="igx-group-label__icon" > group_work</igx-icon >
<span class ="igx-group-label__column-name" >
{{ groupRow.expression.fieldName }}:
</span >
<span class ="igx-group-label__text" > {{ isDate(groupRow.value) ? (groupRow.value | date: dateFormatter) : groupRow.value }}</span >
<igx-badge [value ]="groupRow.records.length" class ='igx-group-label__count-badge' > </igx-badge >
</div >
</ng-template >
</igx-grid >
</div >
html コピー .grid-controls {
display : flex;
flex-flow : column nowrap;
justify-content : space-between;
margin : 0 16px 24px ;
igx-switch {
margin-top : 24px ;
}
}
.grid__wrapper {
padding-top : 16px ;
margin : 0 16px ;
}
.header {
height : 100% ;
}
.igx-grid__th .title {
width : 100% ;
cursor : auto;
}
scss コピー
このサンプルでは、さまざまな日付条件のカスタム ソート ストラテジを定義しています。
各カスタム ストラテジ、ベースの DefaultSortingStrategy
を拡張し、compareValues
メソッドを定義します。値をソートするときに使用されるカスタム比較関数です。さらに、比較に必要な日付から値を抽出します。
class BaseSortingStrategy extends DefaultSortingStrategy {
public getParsedDate (date: any ) {
return {
day : date.getDay(),
month : date.getMonth() + 1 ,
year : date.getFullYear()
};
}
compareValues (a: any , b: any ) {
const dateA = this .getParsedDate(a);
const dateB = this .getParsedDate(b);
return dateA.year < dateB.year ?
-1 : dateA.year > dateB.year ?
1 : dateA.month < dateB.month ?
-1 : dateA.month > dateB.month ?
1 : 0 ;
}
}
class DaySortingStrategy extends BaseSortingStrategy {
compareValues (a: any , b: any ) {
const dateA = this .getParsedDate(a);
const dateB = this .getParsedDate(b);
return dateA.year < dateB.year ?
-1 : dateA.year > dateB.year ?
1 : dateA.month < dateB.month ?
-1 : dateA.month > dateB.month ?
1 : dateA.day < dateB.day ?
-1 : dateA.day > dateB.day ?
1 : 0 ;
}
}
class WeekSortingStrategy extends BaseSortingStrategy {
public getWeekOfDate (a: any ) {
return parseInt (new DatePipe("en-US" ).transform(a, 'w' ), 10 );
}
compareValues (a: any , b: any ) {
const dateA = this .getParsedDate(a);
const dateB = this .getParsedDate(b);
const weekA = this .getWeekOfDate(a);
const weekB = this .getWeekOfDate(b);
return dateA.year < dateB.year ?
-1 : dateA.year > dateB.year ?
1 : weekA < weekB ?
-1 : weekA > weekB ?
1 : 0 ;
}
}
typescript
groupingComparer
関数がグループ化式に対して定義され、選択されたグループ化モードに基づいて同じグループに属するアイテムを決定します。この関数が 0 を返すソートされた値は、同じグループの一部としてマークされます。
groupingComparer: (a, b ) => {
const dateA = this .sortingStrategy.getParsedDate(a);
const dateB = this .sortingStrategy.getParsedDate(b);
if (this .groupByMode === 'Month' ) {
return dateA.month === dateB.month ? 0 : -1 ;
} else if (this .groupByMode === "Year" ) {
return dateA.year === dateB.year ? 0 : -1 ;
} else if (this .groupByMode === "Week" ) {
return this .sortingStrategy.getWeekOfDate(a) === this .sortingStrategy.getWeekOfDate(b) ? 0 : -1 ;
}
return dateA.day === dateB.day && dateA.month === dateB.month ? 0 : -1 ;
}
typescript
バージョン 15.1.0 以降、組み込みのソート ストラテジ GroupMemberCountSortingStrategy
を使用して、メンバー数に基づいて項目をソートすることもできます。
public sortByGroup ( ) {
const expressions = this .grid1.groupingExpressions;
if (expressions.length) {
const fieldName = expressions[0 ].fieldName;
const dir = expressions[0 ].dir === SortingDirection.Asc ? SortingDirection.Desc : SortingDirection.Asc;
this .grid1.groupBy({ fieldName, dir, ignoreCase : false , strategy : GroupMemberCountSortingStrategy.instance() });
}
}
typescript
スタイル設定
igxGridを使用すると、Ignite UI for Angular テーマ ライブラリ
でスタイルを設定できます。グリッドの grid-theme
は、グリッドのすべての機能をカスタマイズできるさまざまなプロパティを公開します。
以下の手順では、グリッドの Group By スタイルをカスタマイズする手順を実行しています。
グローバル テーマのインポート
グループ化機能のカスタマイズは、すべてのスタイリング機能とミックスインが配置されている index
ファイルをインポートする必要があります。
@use "igniteui-angular/theming" as *;
scss
カスタム テーマの定義
次に、grid-theme
を拡張し、必要に応じて Group By をカスタマイズするために必要なパラメーターを受け入れる新しいテーマを作成します。Group By 機能で使用されるため、chip-theme
を拡張する必要もあります。
$custom-theme : grid-theme(
$group-row-background : #494949 ,
$group-row-selected-background : #383838 ,
$group-label-column-name-text : #f8f8f8 ,
$group-label-icon : #ffcd0f ,
$group-label-text : #f8f8f8 ,
$group-count-background : #ffcd0f ,
$group-count-text-color : #000 ,
$expand-icon-color : #ffcd0f ,
$expand-icon-hover-color : rgb(223 , 181 , 13 ),
$cell-active-border-color : #ffcd0f ,
$row-selected-background : #fff6d3 ,
$row-selected-text-color : #000 ,
$drop-indicator-color : #ffcd0f
);
$custom-chips-theme : chip-theme(
$background : #494949 ,
$text-color : #f8f8f8 ,
$hover-text-color : #e7e7e7
);
scss
カスタム カラー パレットの定義
上記で説明したアプローチでは、色の値がハード コーディングされていました。または、柔軟性を高めるために palette
、color
関数を使用することもできます。
palette
は、指定されたプライマリ カラー、セカンダリ カラー、およびサーフェス カラーに基づいてカラー パレットを生成します。
$black-color : #292826 ;
$yellow-color : #ffcd0f ;
$grey-color : #efefef ;
$custom-palette : palette(
$primary : $black-color ,
$secondary : $yellow-color ,
$surface : $grey-color
);
scss
カスタム パレットが生成された後、color
関数を使用して、さまざまな種類の原色と二次色を取得できます。
$custom-theme : grid-theme(
$group-row-background : color($custom-palette , "primary" , 300 ),
$group-row-selected-background : color($custom-palette , "primary" , 400 ),
$group-label-column-name-text :contrast-color($custom-palette , "primary" , 500 ),
$group-label-icon : color($custom-palette , "secondary" , 600 ),
$group-label-text :contrast-color($custom-palette , "primary" , 500 ),
$group-count-background : color($custom-palette , "secondary" , 600 ),
$group-count-text-color : color($custom-palette , "primary" , 400 ),
$expand-icon-color : color($custom-palette , "secondary" , 600 ),
$expand-icon-hover-color : color($custom-palette , "secondary" , 300 ),
$cell-active-border-color : color($custom-palette , "secondary" , 600 )
);
$custom-chips-theme : chip-theme(
$background : color($custom-palette , "primary" , 300 ),
$text-color :contrast-color($custom-palette , "primary" , 500 ),
$hover-text-color :contrast-color($custom-palette , "primary" , 600 )
);
scss
カスタム スキーマの定義
さらに進んで、スキーマ のすべての利点を備えた柔軟な構造を構築できます。スキーマ はテーマを作成させるための方法です。
すべてのコンポーネントに提供される 2 つの事前定義されたスキーマの 1 つを拡張します。この場合、light-grid
を使用します。
$custom-grid-schema : extend(
$light-grid ,
(
group-row-background: (color:('secondary' , 100 )),
group-row-selected-background: (color:('primary' , 400 )),
group-label-column-name-text: (color:('primary' , 600 )),
group-label-icon: (color:('primary' , 600 )),
group-label-text: (color:('secondary' , 700 )),
group-count-background: (color:('primary' , 600 )),
group-count-text-color: (color:('secondary' , 400 )),
expand-icon-color: (color:('primary' , 600 )),
expand-icon-hover-color: (color:('primary' , 400 ))
)
);
scss
カスタム スキーマを適用するには、light
グローバルまたは dark
グローバルを拡張する必要があります。プロセス全体が実際にコンポーネントにカスタム スキーマを提供し、その後、それぞれのコンポーネントテーマに追加します。
$my-custom-schema : extend(
$light-material-schema ,
(
grid: $custom-grid-schema
)
);
$custom-theme : grid-theme(
$palette : $custom-palette ,
$schema : $my-custom-schema
);
scss
カスタム テーマの適用
テーマを適用する最も簡単な方法は、グローバル スタイル ファイルに sass
@include
ステートメントを使用することです。
@include css-vars($custom-theme );
@include css-vars($custom-chips-theme );
scss
スコープ コンポーネント テーマ
カスタム テーマが特定のコンポーネントのみに影響するように、定義したすべてのスタイルをグローバル スタイル ファイルからカスタム コンポーネントのスタイルファイルに移動できます (index
ファイルのインポートを含む)。
このように、Angular の ViewEncapsulation により、スタイルはカスタム コンポーネントにのみ適用されます。
コンポーネントが Emulated
ViewEncapsulation を使用している場合、グリッド内のコンポーネントをスタイル設定するためには、::ng-deep
を使用してこのカプセル化を解除する必要があります。
この例では、チップ テーマに ::ng-deep
を使用する必要があります。
@include css-vars($custom-theme );
:host {
::ng-deep {
@include chip($custom-chips-theme );
}
}
scss
デモ
import { NgModule } from "@angular/core" ;
import { FormsModule } from "@angular/forms" ;
import { BrowserModule } from "@angular/platform-browser" ;
import { BrowserAnimationsModule } from "@angular/platform-browser/animations" ;
import { AppComponent } from "./app.component" ;
import { GridGroupByStylingComponent } from "./grid/grid-groupby-styling/grid-groupby-styling.component" ;
import { IgxGridModule } from "igniteui-angular" ;
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
GridGroupByStylingComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxGridModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー import { Component, ViewChild, ViewEncapsulation } from '@angular/core' ;
import {
DefaultSortingStrategy,
IgxGridComponent,
ISortingExpression,
SortingDirection
} from 'igniteui-angular' ;
import { INVOICE_DATA } from '../../data/invoiceData' ;
@Component ({
encapsulation : ViewEncapsulation.Emulated,
selector : 'app-grid-groupby-sample' ,
styleUrls : ['./grid-groupby-styling.component.scss' ],
templateUrl : './grid-groupby-styling.component.html'
})
export class GridGroupByStylingComponent {
@ViewChild ('grid1' , { read : IgxGridComponent, static : true })
public grid1: IgxGridComponent;
public data;
public expr: ISortingExpression[];
constructor ( ) {
this .data = INVOICE_DATA;
this .expr = [
{ dir : SortingDirection.Asc, fieldName : 'ShipCountry' , ignoreCase : false ,
strategy : DefaultSortingStrategy.instance() },
{ dir : SortingDirection.Asc, fieldName : 'ShipCity' , ignoreCase : false ,
strategy : DefaultSortingStrategy.instance() }
];
}
public formatDate (val: Date ) {
return new Intl .DateTimeFormat('en-US' ).format(val);
}
public formatCurrency (value: number ) {
return '$' + value.toFixed(2 );
}
}
ts コピー <igx-grid
[igxPreventDocumentScroll ]="true"
#grid1
[data ]="data"
[width ]="'100%'"
[height ]="'540px'"
[groupingExpressions ]="expr"
>
<igx-column field ="OrderID" header ="Order ID" [hidden ]="true" > </igx-column >
<igx-column
field ="ShipCountry"
header ="Ship Country"
width ="200px"
[groupable ]="true"
>
</igx-column >
<igx-column
field ="OrderDate"
header ="Order Date"
width ="200px"
[formatter ]="formatDate"
[groupable ]="true"
>
</igx-column >
<igx-column
field ="PostalCode"
header ="Postal Code"
width ="200px"
[groupable ]="true"
>
</igx-column >
<igx-column
field ="Discontinued"
header ="Discontinued"
width ="200px"
[groupable ]="true"
>
<ng-template igxCell let-cell ="cell" let-val >
<img
*ngIf ="val"
src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/active.png"
title ="Continued"
alt ="Continued"
/>
<img
*ngIf ="!val"
src ="https://www.infragistics.com/angular-demos-lob/assets/images/grid/expired.png"
title ="Discontinued"
alt ="Discontinued"
/>
</ng-template >
</igx-column >
<igx-column
field ="ShipName"
header ="Ship Name"
width ="250px"
[groupable ]="true"
>
</igx-column >
<igx-column
field ="ShipCity"
header ="Ship City"
width ="250px"
[groupable ]="true"
>
</igx-column >
<igx-column
field ="ShipperName"
header ="Shipper Name"
width ="250px"
[groupable ]="true"
>
</igx-column >
<igx-column
field ="Salesperson"
header ="Salesperson"
width ="250px"
[groupable ]="true"
>
</igx-column >
<igx-column
field ="UnitPrice"
header ="Unit Price"
width ="150px"
[formatter ]="formatCurrency"
dataType ="number"
[groupable ]="true"
>
</igx-column >
<igx-column
field ="Quantity"
header ="Quantity"
width ="150px"
dataType ="number"
[groupable ]="true"
>
</igx-column >
</igx-grid >
html コピー @use '../../../variables' as *;
$yellow : #ffcd0f ;
$gray : #494949 ;
$light-gray : #f8f8f8 ;
$black : #222 ;
$custom-theme : grid-theme(
$group-row-background : $gray ,
$group-row-selected-background : #383838 ,
$group-label-column-name-text : $light-gray ,
$group-label-icon : $yellow ,
$group-label-text : $light-gray ,
$group-count-background : $yellow ,
$group-count-text-color : $black ,
$expand-icon-color : $yellow ,
$expand-icon-hover-color : rgb(223 , 181 , 13 ),
$cell-active-border-color : $yellow ,
$row-selected-background : #fff6d3 ,
$row-selected-text-color : $black ,
$drop-indicator-color : $yellow
);
$custom-chips-theme : chip-theme(
$background : $gray ,
$text-color : $light-gray ,
$hover-text-color : #e7e7e7
);
:host {
display : block;
padding-top : 16px ;
margin : 0 16px ;
::ng-deep {
@include css-vars($custom-theme );
@include css-vars($custom-chips-theme );
}
}
scss コピー
このサンプルは、Change Theme
(テーマの変更) から選択したグローバル テーマに影響を受けません。
既知の制限
制限
説明
グループ列の最大値は 10 です。
10 列以上の場合はエラーがスローされます。
API リファレンス
その他のリソース
コミュニティに参加して新しいアイデアをご提案ください。