React Tree Grid 상태 지속성
트리 그리드의 Ignite UI for React 상태 지속성을 통해 개발자 React 그리드 상태를 쉽게 저장하고 복원할 수 있습니다. 가 IgrGridState
React에 적용되면 개발자가 모든 시나리오에서 상태 지속성을 달성하는 데 사용할 수 있는 메서드가 getState
applyStateFromString
applyState
getStateAsString
노출됩니다. IgrTreeGrid
지원되는 기능
IgrGridState
다음 기능의 상태 저장 및 복원을 지원합니다.
- 정렬
- 필터링
- 고급 필터링
- 페이징
- CellSelection
- 행 선택
- ColumnSelection
- RowPinning
- 확장
- 그룹화 기준
- Columns
- Multi column headers
- 열 순서
- Column properties defined by the
IColumnState
interface.
용법
이 메서드는 getState
모든 상태 정보를 포함하는 개체의 그리드 상태를 IgrGridStateInfo
반환합니다. 저장하려면 추가 단계가 필요할 수 있습니다.
직 getStateAsString
렬화된 JSON 문자열을 반환하므로 개발자는 이를 가져와 모든 데이터 저장소(데이터베이스, 클라우드, 브라우저 localStorage 등)에 저장할 수 있습니다.
개발자는 기능 이름이 있는 배열을 인수로 전달하여 특정 기능에 대한 상태만 가져오도록 선택할 수 있습니다. 빈 배열은 기본 상태 옵션을 사용하게 됩니다.
<IgrTreeGrid>
<IgrGridState ref={gridStateRef}></IgrGridState>
</IgrTreeGrid>
tsx
// get an `IgrGridStateInfo` object, containing all features original state objects, as returned by the grid public API
const state: IgrGridStateInfo = gridStateRef.current.getState([]);
// get all features` state in a serialized JSON string
const stateString: string = gridStateRef.current.getStateAsString([]);
// get the sorting and filtering expressions
const sortingFilteringStates: IgrGridStateInfo = gridStateRef.current.getState(['sorting', 'filtering']);
tsx
applyState
- 이 메서드는 객체를 IgrGridStateInfo
인수로 받아들이고 객체 또는 지정된 피처에서 발견된 각 피처의 상태를 두 번째 인수로 복원합니다.
applyStateFromString
- 이 메서드는 직렬화된 JSON 문자열을 인수로 받아들이고 JSON 문자열 또는 지정된 기능에서 발견된 각 기능의 상태를 두 번째 인수로 복원합니다.
gridStateRef.current.applyState(gridState, []);
gridStateRef.current.applyStateFromString(gridStateString, []);
gridStateRef.current.applyState(sortingFilteringStates, [])
tsx
객체는 options
인터페이스를 구현합니다 IgrGridStateOptions
., 즉 특정 기능의 이름인 모든 키에 대해 이 기능 상태가 추적되는지 여부를 나타내는 부울 값이 있습니다. getState
/ getStateAsString
methods는 이러한 기능의 상태를 반환된 값에 넣지 않으며 applyState
/ applyStateFromString
methods는 해당 기능의 상태를 복원하지 않습니다.
<IgrGridState options={{ cellSelection: false, sorting: false }}></IgrGridState>
tsx
사용하기 쉬운 단일 지점 API를 사용하면 몇 줄의 코드로 전체 상태 유지 기능을 얻을 수 있습니다. 아래에서 코드를 복사하여 붙여 넣 으십시오 - 사용자가 현재 페이지를 떠날 때마다 브라우저 LocalStorage
개체에 그리드 상태를 저장합니다. 사용자가 기본 페이지로 돌아갈 때마다 그리드 상태가 복원됩니다. 더 이상 원하는 데이터를 얻기 위해 매번 복잡한 고급 필터링 및 정렬 표현식을 구성할 필요가 없습니다 - 한 번만 수행하고 아래 코드가 사용자를 위해 나머지 작업을 수행하도록 합니다.
<IgrTreeGrid onRendered={restoreGridState}>
<IgrGridState ref={gridStateRef}></IgrGridState>
</IgrTreeGrid>
tsx
useEffect(() => {
restoreGridState();
window.addEventListener('beforeunload', saveGridState);
return () => {
window.removeEventListener('beforeunload', saveGridState);
}
}, []);
// Using methods that work with IgrGridStateInfo object.
const saveGridState = () => {
const state = gridStateRef.current.getState([]);
window.localStorage.setItem('grid-state', JSON.stringify(state));
}
const restoreGridState = () => {
const state = window.localStorage.getItem('grid-state');
if (state) {
gridStateRef.current.applyState(JSON.parse(state), []);
}
}
//Or using string alternative methods.
const saveGridState = () => {
const state = gridStateRef.current.getStateAsString([]);
window.localStorage.setItem('grid-state', state);
}
const restoreGridState = () => {
const state = window.localStorage.getItem('grid-state');
if (state) {
gridStateRef.current.applyStateFromString(state, []);
}
}
tsx
데모
export class EmployeesNestedDataItem {
public constructor(init: Partial<EmployeesNestedDataItem>) {
Object.assign(this, init);
}
public ID: number;
public Age: number;
public Salary: number;
public Productivity: number;
public City: string;
public Country: string;
public Phone: string;
public HireDate: string;
public Name: string;
public Title: string;
public Employees: EmployeesNestedDataItem_EmployeesItem[];
}
export class EmployeesNestedDataItem_EmployeesItem {
public constructor(init: Partial<EmployeesNestedDataItem_EmployeesItem>) {
Object.assign(this, init);
}
public Age: number;
public Salary: number;
public Productivity: number;
public City: string;
public Country: string;
public Phone: string;
public HireDate: string;
public ID: number;
public Name: string;
public Title: string;
}
export class EmployeesNestedData extends Array<EmployeesNestedDataItem> {
public constructor(items: Array<EmployeesNestedDataItem> | number = -1) {
if (Array.isArray(items)) {
super(...items);
} else {
const newItems = [
new EmployeesNestedDataItem(
{
ID: 1,
Age: 55,
Salary: 80000,
Productivity: 90,
City: `Berlin`,
Country: `Germany`,
Phone: `609-202-505`,
HireDate: `2008-03-20`,
Name: `John Winchester`,
Title: `Development Manager`,
Employees: [
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 43,
Salary: 70000,
Productivity: 80,
City: `Hamburg`,
Country: `Germany`,
Phone: `609-444-555`,
HireDate: `2011-06-03`,
ID: 3,
Name: `Michael Burke`,
Title: `Senior Software Developer`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 29,
Salary: 60000,
Productivity: 80,
City: `Munich`,
Country: `Germany`,
Phone: `609-333-444`,
HireDate: `2009-06-19`,
ID: 2,
Name: `Thomas Anderson`,
Title: `Senior Software Developer`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 31,
Salary: 90000,
Productivity: 80,
City: `Warasw`,
Country: `Poland`,
Phone: `609-222-205`,
HireDate: `2014-08-18`,
ID: 11,
Name: `Monica Reyes`,
Title: `Software Development Team Lead`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 35,
Salary: 70000,
Productivity: 70,
City: `Koln`,
Country: `Germany`,
Phone: `609-502-525`,
HireDate: `2015-09-17`,
ID: 6,
Name: `Roland Mendel`,
Title: `Senior Software Developer`
})]
}),
new EmployeesNestedDataItem(
{
ID: 4,
Age: 42,
Salary: 90000,
Productivity: 80,
City: `Kielce`,
Country: `Poland`,
Phone: `609-202-505`,
HireDate: `2014-01-22`,
Name: `Ana Sanders`,
Title: `CEO`,
Employees: [
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 44,
Salary: 80000,
Productivity: 80,
City: `Warasw`,
Country: `Poland`,
Phone: `609-202-505`,
HireDate: `2014-04-04`,
ID: 14,
Name: `Laurence Johnson`,
Title: `Director`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 25,
Salary: 85000,
Productivity: 55,
City: `Paris`,
Country: `France`,
Phone: `609-202-505`,
HireDate: `2017-11-09`,
ID: 5,
Name: `Elizabeth Richards`,
Title: `Vice President`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 39,
Salary: 88000,
Productivity: 88,
City: `London`,
Country: `UK`,
Phone: `609-202-505`,
HireDate: `2010-03-22`,
ID: 13,
Name: `Trevor Ashworth`,
Title: `Director`
})]
}),
new EmployeesNestedDataItem(
{
ID: 18,
Age: 49,
Salary: 77000,
Productivity: 70,
City: `Manchester`,
Country: `UK`,
Phone: `222-555-577`,
HireDate: `2014-01-22`,
Name: `Victoria Lincoln`,
Title: `Senior Accountant`,
Employees: [
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 43,
Salary: 70000,
Productivity: 80,
City: `Hamburg`,
Country: `Germany`,
Phone: `609-444-555`,
HireDate: `2011-06-03`,
ID: 23,
Name: `Thomas Burke`,
Title: `Senior Accountant`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 29,
Salary: 60000,
Productivity: 80,
City: `Munich`,
Country: `Germany`,
Phone: `609-333-444`,
HireDate: `2009-06-19`,
ID: 22,
Name: `Michael Anderson`,
Title: `Junior Accountant`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 31,
Salary: 90000,
Productivity: 80,
City: `Warasw`,
Country: `Poland`,
Phone: `609-222-205`,
HireDate: `2014-08-18`,
ID: 21,
Name: `Roland Reyes`,
Title: `Accountant Team Lead`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 35,
Salary: 70000,
Productivity: 70,
City: `Koln`,
Country: `Germany`,
Phone: `609-502-525`,
HireDate: `2015-09-17`,
ID: 24,
Name: `Monica Mendel`,
Title: `Senior Software Developer`
})]
}),
new EmployeesNestedDataItem(
{
ID: 10,
Age: 61,
Salary: 85000,
Productivity: 890,
City: `Lyon`,
Country: `France`,
Phone: `259-266-887`,
HireDate: `2010-01-01`,
Name: `Yang Wang`,
Title: `Localization Developer`,
Employees: [
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 31,
Salary: 90000,
Productivity: 80,
City: `Warasw`,
Country: `Poland`,
Phone: `609-222-205`,
HireDate: `2014-08-18`,
ID: 11,
Name: `Monica Reyes`,
Title: `Software Development Team Lead`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 35,
Salary: 70000,
Productivity: 70,
City: `Koln`,
Country: `Germany`,
Phone: `609-502-525`,
HireDate: `2015-09-17`,
ID: 6,
Name: `Roland Mendel`,
Title: `Senior Software Developer`
})]
}),
new EmployeesNestedDataItem(
{
ID: 35,
Age: 35,
Salary: 75000,
Productivity: 75,
City: `Warasw`,
Country: `Poland`,
Phone: `688-244-844`,
HireDate: `2014-01-22`,
Name: `Janine Munoz`,
Title: `HR`,
Employees: [
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 43,
Salary: 70000,
Productivity: 80,
City: `Hamburg`,
Country: `Germany`,
Phone: `609-444-555`,
HireDate: `2011-06-03`,
ID: 3,
Name: `Michael Burke`,
Title: `Senior Software Developer`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 31,
Salary: 90000,
Productivity: 80,
City: `Warasw`,
Country: `Poland`,
Phone: `609-222-205`,
HireDate: `2014-08-18`,
ID: 11,
Name: `Monica Reyes`,
Title: `Software Development Team Lead`
})]
}),
new EmployeesNestedDataItem(
{
ID: 10,
Age: 49,
Salary: 95000,
Productivity: 80,
City: `Krakow`,
Country: `Poland`,
Phone: `677-266-555`,
HireDate: `2010-01-01`,
Name: `Yang Wang`,
Title: `Sales Manager`,
Employees: [
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 29,
Salary: 60000,
Productivity: 80,
City: `Munich`,
Country: `Germany`,
Phone: `609-333-444`,
HireDate: `2009-06-19`,
ID: 2,
Name: `Thomas Anderson`,
Title: `Senior Software Developer`
}),
new EmployeesNestedDataItem_EmployeesItem(
{
Age: 35,
Salary: 70000,
Productivity: 70,
City: `Koln`,
Country: `Germany`,
Phone: `609-502-525`,
HireDate: `2015-09-17`,
ID: 6,
Name: `Roland Mendel`,
Title: `Senior Software Developer`
})]
}),
];
super(...newItems.slice(0));
}
}
}
tsimport React, { useEffect, useRef, useState } from "react";
import ReactDOM from "react-dom/client";
import {
IgrActionStrip,
IgrColumn,
IgrGridPinningActions,
IgrGridToolbar,
IgrGridToolbarActions,
IgrGridToolbarHiding,
IgrGridToolbarPinning,
IgrPaginator,
IgrGridState,
IgrGridStateOptions,
IgrTreeGrid,
} from "@infragistics/igniteui-react-grids";
import {
IgrButton,
IgrCheckbox,
IgrCheckboxChangeEventArgs,
IgrIcon,
registerIconFromText,
} from "@infragistics/igniteui-react";
import "@infragistics/igniteui-react-grids/grids/themes/light/bootstrap.css";
import "./index.css";
import { EmployeesNestedData } from "./EmployeesNestedData";
const restoreIcon =
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-120q-138 0-240.5-91.5T122-440h82q14 104 92.5 172T480-200q117 0 198.5-81.5T760-480q0-117-81.5-198.5T480-760q-69 0-129 32t-101 88h110v80H120v-240h80v94q51-64 124.5-99T480-840q75 0 140.5 28.5t114 77q48.5 48.5 77 114T840-480q0 75-28.5 140.5t-77 114q-48.5 48.5-114 77T480-120Zm112-192L440-464v-216h80v184l128 128-56 56Z"/></svg>';
const saveIcon =
'<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm2 16H5V5h11.17L19 7.83V19zm-7-7c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zM6 6h9v4H6z"/></svg>';
const clearIcon =
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg>';
const forwardIcon =
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M647-440H160v-80h487L423-744l57-56 320 320-320 320-57-56 224-224Z"/></svg>';
const deleteIcon =
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm400-600H280v520h400v-520ZM360-280h80v-360h-80v360Zm160 0h80v-360h-80v360ZM280-720v520-520Z"/></svg>';
const refreshIcon =
'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-160q-134 0-227-93t-93-227q0-134 93-227t227-93q69 0 132 28.5T720-690v-110h80v280H520v-80h168q-32-56-87.5-88T480-720q-100 0-170 70t-70 170q0 100 70 170t170 70q77 0 139-44t87-116h84q-28 106-114 173t-196 67Z"/></svg>';
export default function App() {
const gridData = new EmployeesNestedData();
const stateKey = "tree-grid-state";
const [allOptions, setAllOptions] = useState(true);
const [options, setOption] = useState<IgrGridStateOptions>({
cellSelection: true,
rowSelection: true,
filtering: true,
advancedFiltering: true,
paging: true,
sorting: true,
columns: true,
expansion: true,
rowPinning: true,
columnSelection: true,
});
const [page, setPage] = useState<number>(0);
const [perPage, setPerPage] = useState<number>(15);
const [totalRecords, setTotalRecords] = useState<number>(gridData.length);
let grid: IgrTreeGrid;
const gridRef = (ref: IgrTreeGrid) => {
grid = ref;
}
const gridStateRef = useRef<IgrGridState>(null);
useEffect(() => {
registerIconFromText("restore", restoreIcon, "material");
registerIconFromText("save", saveIcon, "material");
registerIconFromText("clear", clearIcon, "material");
registerIconFromText("forward", forwardIcon, "material");
registerIconFromText("delete", deleteIcon, "material");
registerIconFromText("refresh", refreshIcon, "material");
restoreGridState();
window.addEventListener("beforeunload", saveGridState);
return () => {
window.removeEventListener("beforeunload", saveGridState);
};
}, []);
const saveGridState = () => {
const state = gridStateRef.current.getStateAsString([]);
window.localStorage.setItem(stateKey, state);
}
const restoreGridState = () => {
const state = window.localStorage.getItem(stateKey);
if (state) {
gridStateRef.current.applyStateFromString(state, []);
}
}
const resetGridState = () => {
setPage(0);
setPerPage(15);
setTotalRecords(gridData.length);
grid.clearFilter(null);
grid.sortingExpressions = [];
grid.deselectAllColumns();
grid.deselectAllRows();
grid.clearCellSelection();
}
const onChange = (e: IgrCheckboxChangeEventArgs) => {
const s = e.target as IgrCheckbox;
if (s.name === "allFeatures") {
const isChecked = e.detail.checked;
setAllOptions(isChecked);
setOption({
cellSelection: isChecked,
rowSelection: isChecked,
filtering: isChecked,
advancedFiltering: isChecked,
paging: isChecked,
sorting: isChecked,
columns: isChecked,
expansion: isChecked,
rowPinning: isChecked,
columnSelection: isChecked,
});
} else {
const newOptions = { ...options };
newOptions[s.name as keyof typeof newOptions] = e.detail.checked;
setOption(newOptions);
}
}
const leavePage = () => {
saveGridState();
window.location.replace("./grids/tree-grid/state-persistence-about");
}
const clearStorage = () => {
window.localStorage.removeItem(stateKey);
}
const reloadPage = () => {
window.location.reload();
}
return (
<div className="vertical sampleContainer">
<div className="container horizontal">
<IgrButton onClick={restoreGridState}>
<IgrIcon name="restore" collection="material"></IgrIcon>
<span>Restore</span>
</IgrButton>
<IgrButton onClick={saveGridState}>
<IgrIcon name="save" collection="material"></IgrIcon>
<span>Save</span>
</IgrButton>
<IgrButton onClick={resetGridState}>
<IgrIcon name="clear" collection="material"></IgrIcon>
<span>Reset</span>
</IgrButton>
<IgrButton onClick={leavePage}>
<IgrIcon name="forward" collection="material"></IgrIcon>
<span>Leave</span>
</IgrButton>
<IgrButton onClick={clearStorage}>
<IgrIcon name="delete" collection="material"></IgrIcon>
<span>Clear</span>
</IgrButton>
<IgrButton onClick={reloadPage}>
<IgrIcon name="refresh" collection="material"></IgrIcon>
<span>Reload</span>
</IgrButton>
</div>
<div className="container horizontal">
<ul>
<li>
Clicking the SAVE button or leaving the page{" "}
<a id="leaveLink" href="./grids/tree-grid/state-persistence-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 className="container horizontal">
<IgrCheckbox name="allFeatures" onChange={onChange} checked={allOptions}>
<span>All Features</span>
</IgrCheckbox>
<IgrCheckbox
name="advancedFiltering"
onChange={onChange}
checked={options.advancedFiltering}
>
<span>Adv. Filtering</span>
</IgrCheckbox>
<IgrCheckbox
name="cellSelection"
onChange={onChange}
checked={options.cellSelection}
>
<span>Cell Selection</span>
</IgrCheckbox>
<IgrCheckbox name="columns" onChange={onChange} checked={options.columns}>
<span>Columns</span>
</IgrCheckbox>
<IgrCheckbox
name="columnSelection"
onChange={onChange}
checked={options.columnSelection}
>
<span>Col Selection</span>
</IgrCheckbox>
<IgrCheckbox
name="expansion"
onChange={onChange}
checked={options.expansion}
>
<span>Expansion</span>
</IgrCheckbox>
<IgrCheckbox
name="filtering"
onChange={onChange}
checked={options.filtering}
>
<span>Filtering </span>
</IgrCheckbox>
<IgrCheckbox name="paging" onChange={onChange} checked={options.paging}>
<span>Paging</span>
</IgrCheckbox>
<IgrCheckbox
name="rowPinning"
onChange={onChange}
checked={options.rowPinning}
>
<span>Row Pinning</span>
</IgrCheckbox>
<IgrCheckbox
name="rowSelection"
onChange={onChange}
checked={options.rowSelection}
>
<span>Row Selection</span>
</IgrCheckbox>
<IgrCheckbox name="sorting" onChange={onChange} checked={options.sorting}>
<span>Sorting</span>
</IgrCheckbox>
</div>
<IgrTreeGrid
ref={gridRef}
data={gridData}
primaryKey="ID"
childDataKey="Employees"
width="95%"
height="500px"
autoGenerate={false}
moving={true}
allowFiltering={true}
allowAdvancedFiltering={true}
filterMode="excelStyleFilter"
columnSelection="multiple"
rowSelection="multiple"
>
<IgrGridState ref={gridStateRef}></IgrGridState>
<IgrGridToolbar>
<IgrGridToolbarActions>
<IgrGridToolbarHiding></IgrGridToolbarHiding>
<IgrGridToolbarPinning></IgrGridToolbarPinning>
</IgrGridToolbarActions>
</IgrGridToolbar>
<IgrActionStrip>
<IgrGridPinningActions></IgrGridPinningActions>
</IgrActionStrip>
<IgrPaginator
page={page}
perPage={perPage}
totalRecords={totalRecords}
onPageChange={(ev) => setPage(ev.detail)}
onPerPageChange={(ev) => setPerPage(ev.detail)}>
</IgrPaginator>
<IgrColumn
field="ID"
header="ID"
sortable={true}
filterable={true}
hidden={true}
></IgrColumn>
<IgrColumn
field="Name"
header="Name"
sortable={true}
filterable={true}
pinned={true}
></IgrColumn>
<IgrColumn
field="Title"
header="Title"
sortable={true}
filterable={true}
></IgrColumn>
<IgrColumn
field="Age"
header="Age"
sortable={true}
filterable={true}
groupable={true}
></IgrColumn>
<IgrColumn
field="Phone"
header="Phone"
sortable={true}
filterable={true}
></IgrColumn>
<IgrColumn
field="OnPTO"
header="On PTO"
sortable={true}
filterable={true}
groupable={true}
></IgrColumn>
</IgrTreeGrid>
</div>
);
}
// rendering above component in the React DOM
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);
tsx/* shared styles are loaded from: */
/* https://static.infragistics.com/xplatform/css/samples */
.horizontal {
gap: 10px;
flex-basis: fit-content;
flex-wrap: wrap;
}
.sampleContainer {
padding: 0.5rem
}
css
제한 사항
getStateAsString
메서드는 JSON.stringify() 메서드를 사용하여 원본 개체를 JSON 문자열로 변환합니다. JSON.stringify()는 함수를 지원하지 않으므로IgrGridState
구성 요소는 열을 무시합니다.Formatter
,filters
,Summaries
,SortStrategy
,CellClasses
,CellStyles
,HeaderTemplate
그리고BodyTemplate
속성.