Grid の状態保持
igxGridState ディレクティブによって開発者がグリッドの状態を簡単に保存および復元できます。IgxGridState
ディレクティブがグリッドに適用されると、getState
および setState
メソッドが公開され、開発者はこれを使用して、あらゆるシナリオで状態の永続化を実現できます。
サポートされている機能
IgxGridState
ディレクティブは、以下の機能の状態の保存および復元をサポートします。
ソート
フィルタリング
高度なフィルタリング
ページング
セルの選択
行の選択
列の選択
行のピン固定
展開
グループ化
列
使用方法
getState
- このメソッドは、シリアル化された JSON 文字列でグリッド状態を返します。これは、開発者がそれを取得して任意のデータストレージ (データベース、クラウド、ブラウザーの localStorage など) に保存できます。このメソッドは最初のオプションのパラメーター serialize
を受け取り、getState
が IGridState
オブジェクトを返すか、シリアル化された JSON 文字列を返すかを決定します。
開発者は、機能名、または機能名を 2 番目の引数として持つ配列を渡すことにより、特定の機能の状態のみを取得することを選択できます。
const gridState = state.getState();
const gridState: IGridState = state.getState(false );
const sortingFilteringStates: IGridState = state.getState(false , ['sorting' , 'filtering' ]);
typescript
setState
- setState
メソッドは、シリアル化されたJSON文字列または IGridState
オブジェクトを引数として受け入れ、オブジェクト/JSON 文字列で見つかった各機能の状態を復元します。
state.setState(gridState);
state.setState(sortingFilteringStates)
typescript
options
- options
オブジェクトは、IGridStateOptions
インターフェースを実装します。特定の機能の名前であるキーには、この機能の状態を追跡するかどうかを示すブール値があります。getState
メソッドはこれらの機能の状態を戻り値に入れず、setState
メソッドはその状態を復元しません。
public options = { cellSelection : false ; sorting: false ; }
typescript
<igx-grid [igxGridState ]="options" > </igx-grid >
html
これらのシンプルなシングル ポイント API を使用すると、わずか数行のコードで完全な状態維持機能を実現できます。下からコードをコピーして貼り付けます - ユーザーが現在のページを離れるたびに、ブラウザーの sessionStorage
オブジェクトにグリッドの状態が保存されます。ユーザーがメイン ページに戻るときに、グリッドの状態が復元されます。必要なデータを取得するために、複雑で高度なフィルタリングやソートの式を毎回設定する必要はなくなりました。一度実行して、以下のコードでユーザーに代わって処理してください。
@ViewChild (IgxGridStateDirective, { static : true })
public state!: IgxGridStateDirective;
public ngOnInit ( ) {
this .router.events.pipe(take(1 )).subscribe((event: NavigationStart ) => {
this .saveGridState();
});
}
public ngAfterViewInit ( ) {
this .restoreGridState();
}
public saveGridState ( ) {
const state = this .state.getState() as string ;
window .sessionStorage.setItem('grid1-state' , state);
}
public restoreGridState ( ) {
const state = window .sessionStorage.getItem('grid1-state' );
this .state.setState(state);
}
typescript
列の復元
可能であれば、State ディレクティブは、新しい列インスタンスを作成するのではなく、状態を復元するときにグリッド上に既に存在する列を再利用します。新しいインスタンスが作成される唯一のシナリオは、列 (または列グループの場合はその子) に field
プロパティがなく、一致する列を一意に識別して再利用する方法がない場合です。
このようなシナリオでは、以下の制限
が課せられます。これらの復元は、アプリケーション レベルのコードで実現できます。テンプレート化された列でこれを行う方法を示します。
テンプレート参照変数 (以下の例では #activeTemplate
) を定義し、columnInit
イベントにイベント ハンドラーを割り当てます。
<igx-grid id ="grid" #grid igxGridState (columnInit )="onColumnInit($event)" >
<igx-column [field ]="'IsActive'" header ="IsActive" >
<ng-template igxCell #activeTemplate let-column let-val ="val" >
<igx-checkbox [checked ]="val" > </igx-checkbox >
</ng-template >
</igx-column >
...
</igx-grid >
html
@ViewChild または @ViewChildren デコレータを使用して、コンポーネントのテンプレート ビューをクエリします。columnInit
イベント ハンドラーで、テンプレートを列の bodyTemplate
プロパティに割り当てます。
@ViewChild ('activeTemplate' , { static : true }) public activeTemplate: TemplateRef<any >;
public onColumnInit (column: IgxColumnComponent ) {
if (column.field === 'IsActive' ) {
column.bodyTemplate = this .activeTemplate;
column.summaries = MySummary;
column.filters = IgxNumberFilteringOperand.instance();
}
}
typescript
デモ
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 { GridSaveStateComponent } from "./grid/grid-save-state/grid-state.component" ;
import {
IgxGridModule,
IgxTooltipModule,
IgxToastModule,
IgxSwitchModule
} from "igniteui-angular" ;
import { AboutComponent } from "./grid/grid-save-state/about.component" ;
import {
Router,
RouterModule
} from "@angular/router" ;
import { IgxPreventDocumentScrollModule } from "./directives/prevent-scroll.directive" ;
@NgModule ({
bootstrap : [AppComponent],
declarations : [
AppComponent,
GridSaveStateComponent,
AboutComponent
],
imports : [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
IgxPreventDocumentScrollModule,
IgxGridModule,
IgxTooltipModule,
RouterModule.forRoot([{component : AboutComponent, path : 'grid-about' },{component : GridSaveStateComponent, path : 'grid-state' },{ path : '' , redirectTo : '/grid-state' , pathMatch : 'full' }]),
IgxToastModule,
IgxSwitchModule
],
providers : [],
entryComponents : [],
schemas : []
})
export class AppModule {}
ts コピー
import { Component, OnInit, ViewChild, ViewChildren, QueryList, AfterViewInit } from '@angular/core' ;
import { NavigationStart, Router } from '@angular/router' ;
import { FilteringExpressionsTree, FilteringLogic, GridFeatures,
IGridState, IGridStateOptions, IgxGridComponent, IgxGridStateDirective,
IgxNumberSummaryOperand, IgxSummaryResult, IgxCheckboxComponent } from 'igniteui-angular' ;
import { take } from 'rxjs/operators' ;
import { employeesData } from './localData' ;
class MySummary {
public operate(data?: any []): IgxSummaryResult[] {
const result = new IgxNumberSummaryOperand().operate(data);
result.push({
key : 'test' ,
label : 'Test' ,
summaryResult : data.filter(rec => rec > 10 && rec < 30 ).length
});
return result;
}
}
@Component ({
selector : 'app-grid' ,
styleUrls : ['./grid-state.component.scss' ],
templateUrl : './grid-state.component.html'
})
export class GridSaveStateComponent implements OnInit , AfterViewInit {
@ViewChild (IgxGridStateDirective, { static : true }) public state: IgxGridStateDirective;
@ViewChild (IgxGridComponent, { static : true }) public grid: IgxGridComponent;
@ViewChildren (IgxCheckboxComponent) public checkboxes: QueryList<IgxCheckboxComponent>;
public localData: any [];
public columns: any [];
public gridId = 'grid1' ;
public stateKey = this .gridId + '-state' ;
public gridState: IGridState;
public serialize = true ;
public features: { key : GridFeatures; shortName: string }[] = [
{ key : 'advancedFiltering' , shortName : 'Adv Filt' },
{ key : 'cellSelection' , shortName : 'Cell Sel' },
{ key : 'columns' , shortName : 'Columns' } ,
{ key : 'columnSelection' , shortName : 'Cols Sel' },
{ key : 'expansion' , shortName : 'Expansion' },
{ key : 'filtering' , shortName : 'Filt' },
{ key : 'paging' , shortName : 'Paging' },
{ key : 'rowPinning' , shortName : 'Row Pining' },
{ key : 'rowSelection' , shortName : 'Row Sel' },
{ key : 'sorting' , shortName : 'Sorting' },
{ key : 'groupBy' , shortName : 'GroupBy' }
];
public options: IGridStateOptions = {
cellSelection : true ,
rowSelection : true ,
filtering : true ,
advancedFiltering : true ,
paging : true ,
sorting : true ,
groupBy : true ,
columns : true ,
expansion : true ,
rowPinning : true ,
columnSelection : true
};
public initialColumns: any [] = [
{ field : 'FirstName' , header : 'First Name' , width : '150px' , dataType : 'string' , pinned : true , sortable : true , filterable : true },
{ field : 'LastName' , header : 'Last Name' , width : '150px' , dataType : 'string' , pinned : true , sortable : true , filterable : true },
{ field : 'Country' , header : 'Country' , width : '140px' , dataType : 'string' , groupable : true , sortable : true , filterable : true , resizable : true },
{ field : 'Age' , header : 'Age' , width : '110px' , dataType : 'number' , sortable : true , filterable : true , hasSummary : true , resizable : true , summaries : MySummary},
{ field : 'RegistererDate' , header : 'Registerer Date' , width : '180px' , dataType : 'date' , sortable : true , filterable : true , resizable : true },
{ field : 'IsActive' , header : 'Is Active' , width : '140px' , dataType : 'boolean' , groupable : true , sortable : true , filterable : true }
];
constructor (private router: Router ) {}
public ngOnInit ( ) {
this .localData = employeesData;
this .columns = this .initialColumns;
this .router.events.pipe(take(1 )).subscribe((event: NavigationStart ) => {
this .saveGridState();
});
}
public ngAfterViewInit ( ) {
this .restoreGridState();
}
public saveGridState ( ) {
const state = this .state.getState(this .serialize);
if (typeof state === 'string' ) {
window .localStorage.setItem(this .stateKey, state);
} else {
window .localStorage.setItem(this .stateKey, JSON .stringify(state));
}
}
public restoreGridState ( ) {
const state = window .localStorage.getItem(this .stateKey);
if (state) {
this .state.setState(state);
}
}
public restoreFeature (stateDirective: IgxGridStateDirective, feature: string ) {
const state = this .getFeatureState(this .stateKey, feature);
if (state) {
const featureState = { } as IGridState;
featureState[feature] = state;
stateDirective.setState(featureState);
}
}
public getFeatureState (stateKey: string , feature: string ) {
let state = window .localStorage.getItem(stateKey);
state = state ? JSON .parse(state)[feature] : null ;
return state;
}
public resetGridState ( ) {
const grid: IgxGridComponent = this .grid;
const pagingState = {index : 0 , recordsPerPage : 15 , metadata : { countPages : 3 , countRecords : this .localData.length}};
grid.pagingState = pagingState;
grid.filteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And);
grid.advancedFilteringExpressionsTree = new FilteringExpressionsTree(FilteringLogic.And);
grid.sortingExpressions = [];
grid.groupingExpressions = [];
grid.deselectAllColumns();
grid.deselectAllRows();
grid.clearCellSelection();
}
public onChange (event: any , action: string ) {
if (action === 'toggleAll' ) {
this .checkboxes.forEach(cb => {
cb.checked = event.checked;
});
for (const key of Object .keys(this .options)) {
this .state.options[key] = event.checked;
}
return ;
}
this .state.options[action] = event.checked;
}
public clearStorage ( ) {
window .localStorage.removeItem(this .stateKey);
}
public reloadPage ( ) {
window .location.reload();
}
}
ts コピー <div class ="grid__wrapper" >
<div class ="controls-holder" >
<div class ="switches" >
<button igxButton ="raised" (click )="restoreGridState()" >
<igx-icon class ="btn-icon" > restore</igx-icon >
<span > Restore</span >
</button >
<button igxButton ="raised" (click )="saveGridState()" >
<igx-icon class ="btn-icon" > save</igx-icon >
<span > Save</span >
</button >
<button igxButton ="raised" (click )="resetGridState()" >
<igx-icon class ="btn-icon" > clear</igx-icon >
<span > Reset</span >
</button >
<button igxButton ="raised" [routerLink ]="['../grid-about']" >
<igx-icon class ="btn-icon" > forward</igx-icon >
<span > Leave</span >
</button >
<button igxButton ="raised" (click )="clearStorage()" >
<igx-icon class ="btn-icon" > delete</igx-icon >
<span > Clear</span >
</button >
<button igxButton ="raised" (click )="reloadPage()" >
<igx-icon class ="btn-icon" > refresh</igx-icon >
<span > Reload</span >
</button >
</div >
<div class ="switches" >
<ul >
<li > Clicking the SAVE button or leaving the page <a [routerLink ]="['../grid-about']" > <strong > here</strong > </a > will save grid state to localStorage.</li >
<li > Use the control buttons to SAVE / RESTORE / RESET / DELETE / grid state or LEAVE the page.</li >
<li > Select/Deselect checkboxes to control saving / restoring feature state.</li >
</ul >
</div >
<div class ="switches" >
<div class ="control-item" >
<igx-checkbox [checked ]="true" (change )="onChange($event, 'toggleAll')" > All</igx-checkbox >
</div >
<div class ="control-item" *ngFor ="let f of features" >
<igx-checkbox (change )="onChange($event, f.key)" [checked ]="options[f.key]" >
{{ f.shortName }}
</igx-checkbox >
</div >
</div >
</div >
<igx-grid [igxPreventDocumentScroll ]="true" [id ]="gridId" #grid1 [igxGridState ]="options"
width ="98%" height ="530px" [autoGenerate ]="false" [moving ]="true"
[data ]="localData"
[primaryKey ]="'EmployeeID'"
[rowEditable ]="false"
[allowFiltering ]="true" [filterMode ]="'excelStyleFilter'"
[allowAdvancedFiltering ]="true"
[displayDensity ]="'cosy'"
[cellSelection ]="'multiple'"
[rowSelection ]="'none'" >
<igx-paginator > </igx-paginator >
<igx-grid-toolbar >
<igx-grid-toolbar-actions >
<igx-grid-toolbar-hiding > </igx-grid-toolbar-hiding >
<igx-grid-toolbar-pinning > </igx-grid-toolbar-pinning >
</igx-grid-toolbar-actions >
</igx-grid-toolbar >
<igx-column *ngFor ="let c of columns"
[sortable ]="c.sortable"
[editable ]="true"
[hasSummary ]="c.hasSummary"
[filterable ]="c.filterable"
[groupable ]="c.groupable"
[field ]="c.field"
[header ]="c.header"
[dataType ]="c.dataType"
[pinned ]="c.pinned"
[hidden ]="c.hidden" >
</igx-column >
</igx-grid >
</div >
html コピー .controls-holder {
display : flex;
justify-content : space-between;
align-items : center;
flex-wrap : wrap;
width : 100% ;
}
.switches {
display : flex;
justify-content : space-between;
justify-content : flex-start;
align-items : center;
flex : 1 0 0% ;
min-width : 100% ;
padding-right : 20px ;
font-size : 0.9rem ;
margin-top : 0 ;
> button {
margin-right : 10px ;
}
}
.control-item {
display : block;
padding : 8px 0px ;
> span {
cursor : pointer;
}
margin-right : 10px ;
}
.grid__wrapper {
margin : 0 16px ;
padding-top : 16px ;
width : 100% ;
}
scss コピー
このサンプルが気に入りましたか? 完全な Ignite UI for Angularツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。
ストラテジの復元
IgxGridState
はデフォルトでは、リモート操作もカスタム ディメンション ストラテジ (詳細については、グリッド リモート操作 サンプルを参照) も保持しません (制限
を参照)。これらの復元は、アプリケーション レベルのコードで実現できます。IgxGridState
は、stateParsed
と呼ばれるイベントを公開します。このイベントはグリッド状態に追加の変更を、それが適用される前に行なうために使用できます。
以下はその方法です。
カスタム ソート方法およびカスタム列/行ディメンション ストラテジを設定します。
<igx-grid #grid
[data ]="data"
[igxGridState ]="options"
[sortStrategy ]="customStrategy"
[height ]="'500px'" >
</igx-grid >
html
@ViewChild (IgxGridStateDirective, { static : true })
public state!: IgxGridStateDirective;
public customStrategy = NoopSortingStrategy.instance();
public options: IGridStateOptions = {...};
typescript
sessionStorage
から状態を復元し、カスタム ストラテジを適用します。
public restoreState ( ) {
const state = window .sessionStorage.getItem('grid-state' );
this .state.stateParsed.pipe(take(1 )).subscribe(parsedState => {
parsedState.sorting.forEach(x => x.strategy = NoopSortingStrategy.instance());
});
this .state.setState(state as string );
}
typescript
制限
API リファレンス
その他のリソース