Web Components Pivot Grid State Persistence

    The Ignite UI for Web Components State Persistence in Web Components Pivot Grid allows developers to easily save and restore the grid state. When the IgcGridState is applied on the Web Components IgcPivotGridComponent, it exposes the GetState, GetStateAsString, ApplyState and ApplyStateFromString methods that developers can use to achieve state persistence in any scenario.

    Supported Features

    IgcGridState directive supports saving and restoring the state of the following features:

    Usage

    The getState method returns the grid state in a IgcGridStateInfo object, containing all the state info. Additional steps may be required in order to save it.

    The GetStateAsString returns a serialized JSON string, so developers can just take it and save it on any data storage (database, cloud, browser localStorage, etc).

    The developer may choose to get only the state for a certain feature/features, by passing in an array with feature names as an argument. Empty array will result to using the default state options.

    <igc-pivot-grid id="grid">
        <igc-grid-state id="gridState"></igc-grid-state>
    </igc-pivot-grid>
    
    var gridState = document.getElementById('gridState') as IgcGridStateComponent;
    
    // get an `IgcGridStateInfo` object, containing all features original state objects, as returned by the grid public API
    const state: IgcGridStateInfo = gridState.getState();
    
    // get all features` state in a serialized JSON string
    const stateString: string = gridState.getStateAsString();
    
    // get the sorting and filtering expressions
    const sortingFilteringStates: IgcGridStateInfo = gridState.getState(['sorting', 'filtering']);
    

    ApplyState - The method accepts a IgcGridStateInfo object as argument and will restore the state of each feature found in the object or specified features as second argument.

    ApplyStateFromString - The method accepts a serialized JSON string as argument and will restore the state of each feature found in the JSON string or specified features as second argument.

    gridState.applyState(gridState);
    gridState.applyStateFromString(gridStateString);
    gridState.applyState(sortingFilteringStates)
    

    The Options object implements the IgcGridStateOptions interface, i.e. for every key, which is the name of a certain feature, there is the boolean value indicating if this feature state will be tracked. GetState/GetStateAsString methods will not put the state of these features in the returned value and ApplyState/ApplyStateFromString methods will not restore state for them.

    gridState.options = { cellSelection: false, sorting: false };
    

    The simple to use single-point API's allows to achieve a full state persistence functionality in just a few lines of code. Copy paste the code from below - it will save the grid state in the browser LocalStorage object every time the user leaves the current page. Whenever the user returns to main page, the grid state will be restored. No more need to configure those complex advanced filtering and sorting expressions every time to get the data you want - do it once and have the code from below do the rest for your users:

    constructor() {
        window.addEventListener("load", () => { this.restoreGridState(); });
        window.addEventListener("beforeunload", () => { this.saveGridState(); });
    }
    
    // Using methods that work with IgcGridStateInfo object.
    public saveGridState() {
        const state = this.gridState.getState();
        window.localStorage.setItem('grid-state', JSON.stringify(state));
    }
    
    public restoreGridState() {
        const state = window.localStorage.getItem('grid-state');
        if (state) {
            this.gridState.applyState(JSON.parse(state));
        }
    }
    
    // Or using string alternative methods.
    public saveGridStateString() {
        const state = this.gridState.getStateAsString();
        window.localStorage.setItem('grid-state', state);
    }
    
    public restoreGridStateString() {
        const state = window.localStorage.getItem('grid-state');
        if (state) {
            this.gridState.applyStateFromString(state);
        }
    }
    

    Restoring Pivot Configuration

    IgcGridState will not persist pivot dimension functions, value formatters, etc. by default (see limitations). Restoring any of these can be achieved with code on application level. The IgcPivotGridComponent exposes two events which can be used to set back any custom functions you have in the configuration: DimensionInit and ValueInit. Let's show how to do this:

    • Assign event handlers for the DimensionInit and ValueInit events:
     constructor() {
        var grid = document.getElementById('grid') as IgcPivotGridComponent;
        grid.pivotConfiguration = this.pivotConfiguration;
        grid.addEventListener("valueInit", (ev:any) => this.onValueInit(ev));
        grid.addEventListener("dimensionInit", (ev:any) => this.onDimensionInit(ev));
    }
    

    The DimensionInit and ValueInit events are emitted for each value and dimension defined in the pivotConfiguration property.

    • In the ValueInit event handler set all custom aggregators, formatters and styles:
    public onValueInit(event: any) {
        const value: IgcPivotValue = event.detail;
        if (value.member === 'AmountofSale') {
            value.aggregate.aggregator = this.totalSale;
            value.aggregateList?.forEach((aggr: any) => {
                switch (aggr.key) {
                    case 'SUM':
                        aggr.aggregator = this.totalSale;
                        break;
                    case 'MIN':
                        aggr.aggregator = this.totalMin;
                        break;
                    case 'MAX':
                        aggr.aggregator = this.totalMax;
                        break;
                }
            });
        } else if (value.member === 'Value') {
            value.formatter = (value: any) => value ? '$' + parseFloat(value).toFixed(3) : undefined;
            value.styles.upFontValue = (rowData: any, columnKey: any): boolean => parseFloat(rowData.aggregationValues.get(columnKey.field)) > 150
            value.styles.downFontValue = (rowData: any, columnKey: any): boolean => parseFloat(rowData.aggregationValues.get(columnKey.field)) <= 150;
        }
    }
    
    • In the DimensionInit event handler set all custom MemberFunction implementations:
    public onDimensionInit(event: any) {
        const dim: IgcPivotDimension = event.detail;
        switch (dim.memberName) {
            case 'AllProducts':
                dim.memberFunction = () => 'All Products';
                break;
            case 'ProductCategory':
                dim.memberFunction = (data: any) => data.ProductName;
                break;
            case 'City':
                dim.memberFunction = (data: any) => data.City;
                break;
            case 'SellerName':
                dim.memberFunction = (data: any) => data.SellerName;
                break;
        }
    }
    

    Demo

    Restoring Pivot Strategies

    IgcGridState will not persist neither remote pivot operations nor custom dimension strategies.

    Restoring any of these can be achieved with code on application level. The IgcGridState exposes an event called StateParsed which can be used to additionally modify the grid state before it gets applied. Let's show how to do this:

    StateParsed is only emitted when we are using SetState with string argument.

    • Set custom sorting strategy and custom pivot column and row dimension strategies:
    public pivotConfiguration: IgcPivotConfiguration = {
        columnStrategy: IgcNoopPivotDimensionsStrategy.instance(),
        rowStrategy: IgcNoopPivotDimensionsStrategy.instance(),
        columns: [...],
        rows: [...],
        values: [...],
        filters: [...]
    };
    private gridState: IgcGridStateComponent;
    
    constructor() {
        var grid = document.getElementById("grid") as IgcPivotGridComponent;
        this.gridState = document.getElementById('gridState') as IgcGridStateComponent;
        grid.pivotConfiguration = this.pivotConfiguration;
        PivotNoopData.getData().then((value) => {
            grid.data = value;
        });
        this.gridState.addEventListener('stateParsed', (ev:any) => this.stateParsedHandler(ev) );
    }
    
    • Restoring the state from the LocalStorage and applying the custom strategies looks like the following:
    public restoreGridState() {
        const state = window.localStorage.getItem(this.stateKey);
        if (state) {
            this.gridState.applyStateFromString(state);
        }
    }
    
    public stateParsedHandler(ev: any) {
        const parsedState = ev.detail;
        parsedState.pivotConfiguration.rowStrategy = IgcNoopPivotDimensionsStrategy.instance();
        parsedState.pivotConfiguration.columnStrategy = IgcNoopPivotDimensionsStrategy.instance();
    }
    

    Limitations

    • getState method uses JSON.stringify() method to convert the original objects to a JSON string. JSON.stringify() does not support Functions, thats why the IgcGridState directive will ignore the pivot dimension MemberFunction, pivot values Member, Formatter, custom Aggregate functions, Styles and pivot configuration strategies: ColumnStrategy and RowStrategy.