Angular 계층적 그리드 상태 지속성
igxGridState 지시문을 사용하면 개발자가 그리드 상태를 쉽게 저장하고 복원할 수 있습니다. IgxGridState
지시문이 그리드에 적용되면 개발자가 모든 시나리오에서 상태 지속성을 달성하는 데 사용할 수 있는 getState
및 setState
메서드가 노출됩니다.
Supported Features
IgxGridState
지시문은 다음 기능의 상태 저장 및 복원을 지원합니다.
RowIslands
계층 구조 아래의 모든 하위 그리드에 대한 저장/복원 기능
Sorting
Filtering
Advanced Filtering
Paging
Cell Selection
Row Selection
Column Selection
Row Pinning
Expansion
Columns
Multi column headers
열 순서
IColumnState
인터페이스에 의해 정의된 열 속성입니다.
열 템플릿 및 함수는 애플리케이션 수준 코드를 사용하여 복원됩니다. 열 복원 섹션을 참조하세요.
The Row Selection
feature requires the primaryKey
property to be set, so it can be stored/restored correctly.
Usage
getState
- 이 방법은 직렬화된 JSON 문자열로 그리드 상태를 반환하므로 개발자는 이를 가져와 모든 데이터 저장소(데이터베이스, 클라우드, 브라우저 localStorage 등)에 저장할 수 있습니다. 이 메소드는 첫 번째 선택적 매개변수를 허용합니다. serialize
, 여부를 결정합니다. getState
반환합니다 IGridState
객체 또는 직렬화된 JSON 문자열. 개발자는 기능 이름 또는 기능 이름이 포함된 배열을 두 번째 인수로 전달하여 특정 기능에 대한 상태만 가져오도록 선택할 수 있습니다.
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-hierarchical-grid [igxGridState ]="options" > </igx-hierarchical-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
Restoring columns
가능한 경우 state 지시문은 상태를 복원할 때 새 열 인스턴스를 만드는 대신 그리드에 이미 존재하는 열을 재사용합니다. 새 인스턴스가 생성되는 유일한 시나리오는 열(또는 열 그룹의 경우 자식)에 속성이 없으므로 field
일치하는 열을 고유하게 식별하고 다시 사용할 수 있는 방법이 없는 경우입니다.
이러한 시나리오의 경우 다음이 limitations
적용됩니다. 이 경우 응용 프로그램 수준의 코드를 사용하여 복잡한 개체를 복원할 수 있습니다. 템플릿 열에 대해 이 작업을 수행하는 방법을 보여 드리겠습니다.
템플릿 참조 변수(아래 예에서는 #activeTemplate
)를 정의하고 columnInit
이벤트에 대한 이벤트 핸들러를 할당합니다.
<igx-hierarchical-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-hierarchical-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
Restoring Child Grids
하위 그리드의 상태 저장/복원은 rowIslands
속성에 의해 제어되며 기본적으로 활성화됩니다. IgxGridState
루트 그리드와 계층 구조 아래의 모든 하위 그리드 모두에 대해 기능을 저장/복원하는 데 동일한 옵션을 사용합니다. 예를 들어 다음 옵션을 전달하는 경우:
<igx-grid [igxGridState ]="options" > </igx-grid >
html
그런 다음 getState
API는 selection
및 sorting
제외한 모든 그리드(루트 그리드 및 하위 그리드) 기능에 대한 상태를 반환합니다. 나중에 개발자가 모든 그리드의 filtering
상태만 복원하려는 경우 다음을 사용하세요.
this .state.setState(state, ['filtering' , 'rowIslands' ]);
typescript
Demo
import { Component, OnInit, ViewChild, ViewChildren, QueryList, AfterViewInit } from '@angular/core' ;
import { NavigationStart, Router, RouterLink } from '@angular/router' ;
import { GridFeatures, IGridState, IGridStateOptions, IgxGridStateDirective, IgxHierarchicalGridComponent, IgxNumberSummaryOperand, IgxSummaryResult, IgxCheckboxComponent, IgxButtonDirective, IgxIconComponent, IgxPaginatorComponent, IgxGridToolbarComponent, IgxGridToolbarActionsComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent, IgxColumnComponent, IgxCellTemplateDirective, IgxRowIslandComponent } from 'igniteui-angular' ;
import { take } from 'rxjs/operators' ;
import { SINGERS } from '../../data/singersData' ;
import { IgxPreventDocumentScrollDirective } from '../../directives/prevent-scroll.directive' ;
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-hgrid' ,
styleUrls : ['./hGrid-state.component.scss' ],
templateUrl : './hGrid-state.component.html' ,
imports : [IgxButtonDirective, IgxIconComponent, RouterLink, IgxCheckboxComponent, IgxHierarchicalGridComponent, IgxGridStateDirective, IgxPreventDocumentScrollDirective, IgxPaginatorComponent, IgxGridToolbarComponent, IgxGridToolbarActionsComponent, IgxGridToolbarHidingComponent, IgxGridToolbarPinningComponent, IgxColumnComponent, IgxCellTemplateDirective, IgxRowIslandComponent]
})
export class HGridSaveStateComponent implements OnInit , AfterViewInit {
@ViewChild (IgxGridStateDirective, { static : true }) public state: IgxGridStateDirective;
@ViewChild ('hierarchicalGrid' , { static : true }) public hGrid: IgxHierarchicalGridComponent;
@ViewChildren (IgxCheckboxComponent) public checkboxes: QueryList<IgxCheckboxComponent>;
public localData: any [];
public columns: any [];
public gridId = 'hGrid1' ;
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 : 'rowIslands' , shortName : 'Row Islands' }
];
public options: IGridStateOptions = {
cellSelection : true ,
rowSelection : true ,
filtering : true ,
advancedFiltering : true ,
paging : true ,
sorting : true ,
columns : true ,
expansion : true ,
rowPinning : true ,
columnSelection : true
};
constructor (private router: Router ) {
this .localData = SINGERS;
}
public ngOnInit ( ) {
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 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();
}
public formatter = (a ) => a;
}
ts コピー <div class ="grid__wrapper" >
<div class ="controls-holder" >
<div class ="switches" >
<button igxButton ="contained" (click )="restoreGridState()" >
<igx-icon class ="btn-icon" > restore</igx-icon >
<span > Restore</span >
</button >
<button igxButton ="contained" (click )="saveGridState()" >
<igx-icon class ="btn-icon" > save</igx-icon >
<span > Save</span >
</button >
<button igxButton ="contained" [routerLink ]="['../hGrid-state-about']" >
<igx-icon class ="btn-icon" > forward</igx-icon >
<span > Leave</span >
</button >
<button igxButton ="contained" (click )="clearStorage()" >
<igx-icon class ="btn-icon" > delete</igx-icon >
<span > Clear</span >
</button >
<button igxButton ="contained" (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 ]="['../hGrid-state-about']" > <strong > here</strong > </a > will save grid state to localStorage.</li >
<li > Use the control buttons to SAVE / RESTORE / 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 >
@for (f of features; track f) {
<div class ="control-item" >
<igx-checkbox (change )="onChange($event, f.key)" [checked ]="options[f.key]" >
{{ f.shortName }}
</igx-checkbox >
</div >
}
</div >
</div >
<igx-hierarchical-grid [igxPreventDocumentScroll ]="true" #hierarchicalGrid class ="hgrid" igxGridState
[data ]="localData" [height ]="'500px'" [width ]="'98%'" [rowHeight ]="'65px'"
[primaryKey ]="'Photo'"
[autoGenerate ]="false"
[columnSelection ]="'multiple'"
[cellSelection ]="'multiple'" >
<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 field ="Artist" [sortable ]="true" > </igx-column >
<igx-column field ="Photo" [editable ]="false" [sortable ]="true" >
<ng-template igxCell let-cell ="cell" >
<div class ="cell__inner_2" >
<img [src ]="cell.value" class ="photo" />
</div >
</ng-template >
</igx-column >
<igx-column field ="Debut" dataType ="number" [formatter ]="formatter" [sortable ]="true" > </igx-column >
<igx-column field ="GrammyNominations" header ="Grammy Nominations" dataType ="number" [sortable ]="true" > </igx-column >
<igx-column field ="GrammyAwards" header ="Grammy Awards" dataType ="number" [sortable ]="true" > </igx-column >
<igx-row-island [height ]="null" [key ]="'Albums'"
[autoGenerate ]="false"
[primaryKey ]="'Album'"
rowSelection ='multiple'
[allowFiltering ]='true'
[columnSelection ]="'multiple'"
[cellSelection ]="'multiple'" >
<igx-column field ="Album" [sortable ]="true" > </igx-column >
<igx-column field ="LaunchDate" header ="Launch Date" [dataType ]="'date'" [sortable ]="true" > </igx-column >
<igx-column field ="BillboardReview" header ="Billboard Review" [sortable ]="true" > </igx-column >
<igx-column field ="USBillboard200" header ="US Billboard 200" [sortable ]="true" > </igx-column >
<igx-row-island [height ]="null" [key ]="'Songs'"
[autoGenerate ]="false"
[primaryKey ]="'Number'"
rowSelection ='multiple'
[allowFiltering ]='true'
[columnSelection ]="'multiple'"
[cellSelection ]="'multiple'" >
<igx-column field ="Number" header ="No." [sortable ]="true" > </igx-column >
<igx-column field ="Title" [sortable ]="true" > </igx-column >
<igx-column field ="Released" dataType ="date" [sortable ]="true" > </igx-column >
<igx-column field ="Genre" > </igx-column >
</igx-row-island >
</igx-row-island >
<igx-row-island [height ]="null" [key ]="'Tours'"
[autoGenerate ]="false"
[primaryKey ]="'Tour'"
rowSelection ='multiple'
[allowFiltering ]='true'
[columnSelection ]="'multiple'"
[cellSelection ]="'multiple'" >
<igx-column field ="Tour" [sortable ]="true" > </igx-column >
<igx-column field ="StartedOn" header ="Started on" [sortable ]="true" > </igx-column >
<igx-column field ="Location" [sortable ]="true" > </igx-column >
<igx-column field ="Headliner" [sortable ]="true" > </igx-column >
</igx-row-island >
</igx-hierarchical-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 {
--ig-size: var(--ig-size-medium);
margin : 0 16px ;
padding-top : 10px ;
width : 100% ;
}
scss コピー
Like this sample? Get access to our complete Ignite UI for Angular toolkit and start building your own apps in minutes. Download it for free.
Limitations
모든 그리드 기능을 한 번에 복원하는 경우(매개변수 없이 setState
API 사용) 루트 그리드의 열 속성이 기본값으로 재설정될 수 있습니다. 이런 일이 발생하면 그 후에 열 또는 열 선택 기능을 별도로 복원하십시오.
state.setState(gridState);
state.setState(gridState.columns);
state.setState(gridState.columnSelection);
typescript
API References
Additional Resources