Angular 계층적 그리드 상태 지속성
igxGridState 지시문을 사용하면 개발자가 그리드 상태를 쉽게 저장하고 복원할 수 있습니다. IgxGridState
지시문이 그리드에 적용되면 개발자가 모든 시나리오에서 상태 지속성을 달성하는 데 사용할 수 있는 getState
및 setState
메서드가 노출됩니다.
지원되는 기능
IgxGridState
지시문은 다음 기능의 상태 저장 및 복원을 지원합니다.
RowIslands
계층 구조 아래의 모든 하위 그리드에 대한 저장/복원 기능
Sorting
Filtering
Advanced Filtering
Paging
Cell Selection
Row Selection
Column Selection
Row Pinning
Expansion
Columns
Multi column headers
열 순서
IColumnState
인터페이스에 의해 정의된 열 속성입니다.
열 템플릿 및 함수는 애플리케이션 수준 코드를 사용하여 복원됩니다. 열 복원 섹션을 참조하세요.
이 Row Selection
기능을 사용하려면 primaryKey
속성을 올바르게 저장/복원할 수 있도록 속성을 설정해야 합니다.
용법
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
열 복원 중
가능한 경우 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
하위 그리드 복원
하위 그리드의 상태 저장/복원은 rowIslands
속성에 의해 제어되며 기본적으로 활성화됩니다. IgxGridState
루트 그리드와 계층 구조 아래의 모든 하위 그리드 모두에 대해 기능을 저장/복원하는 데 동일한 옵션을 사용합니다. 예를 들어 다음 옵션을 전달하는 경우:
<igx-grid [igxGridState ]="options" > </igx-grid >
html
그런 다음 getState
API는 selection
및 sorting
제외한 모든 그리드(루트 그리드 및 하위 그리드) 기능에 대한 상태를 반환합니다. 나중에 개발자가 모든 그리드의 filtering
상태만 복원하려는 경우 다음을 사용하세요.
this .state.setState(state, ['filtering' , 'rowIslands' ]);
typescript
데모
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 コピー
이 샘플이 마음에 드시나요? 전체 Ignite UI for Angular 툴킷에 액세스하고 몇 분 안에 나만의 앱을 구축해 보세요. 무료로 다운로드하세요.
제한 사항
모든 그리드 기능을 한 번에 복원하는 경우(매개변수 없이 setState
API 사용) 루트 그리드의 열 속성이 기본값으로 재설정될 수 있습니다. 이런 일이 발생하면 그 후에 열 또는 열 선택 기능을 별도로 복원하십시오.
state.setState(gridState);
state.setState(gridState.columns);
state.setState(gridState.columnSelection);
typescript
API 참조
추가 리소스