Random Developer
Random Developer

Reputation: 175

JqGrid - Trigger reload inside loadComplete event

I would like to be able to reload a jqgrid in the event that the page number is higher than the total pages inside the loadComplete event. I am saving the grid settings to the browser local storage as in this answer - Persisting jqGrid column preferences

I have added a call to trigger the reload of the grid and set the page back to 1, but it doesn't seem to work inside the loadComplete method. I have debugged the code and the method is called.

Javascript: (Important part is loadComplete function in the jqGrid definition)

$(document).ready(function() {          
    var $grid = $('#grid'),
    cm = [ 
        { name: 'Id', index: 'Id', width: 120, align: 'left', editable: false,sortable: true,hidden: true,hidedlg: true,Key: true}, 
        { name: 'Status', index: 'Status', width: 80, align: 'left', editable: false,sortable: true,hidden: true,hidedlg: false,Key: false}, 
        { name: 'Reference', index: 'Reference', width: 80, align: 'left', editable: false,sortable: true,hidden: false,hidedlg: false,Key: false}, 
        { name: 'CustomerReference', index: 'CustomerReference', width: 140, align: 'left', editable: false,sortable: true,hidden: false,hidedlg: false,Key: false}, 
        { name: 'Logged', index: 'Logged', width: 100, align: 'left', editable: false,sortable: true,hidden: false,hidedlg: false,Key: false}
     ],
     saveObjectInLocalStorage = function (storageItemName, object) {
         if (typeof window.localStorage !== 'undefined') {
             window.localStorage.setItem(storageItemName, JSON.stringify(object));
         }
     },
     removeObjectFromLocalStorage = function (storageItemName) {
         if (typeof window.localStorage !== 'undefined') {
             window.localStorage.removeItem(storageItemName);
         }
     },
     getObjectFromLocalStorage = function (storageItemName) {
         if (typeof window.localStorage !== 'undefined') {
             return $.parseJSON(window.localStorage.getItem(storageItemName));
         }
     },
     myColumnStateName = function (grid) {
         return window.location.pathname + '#' + grid[0].id;
     },
     saveColumnState = function (perm) {
         var colModel = this.jqGrid('getGridParam', 'colModel'), i, l = colModel.length, colItem, cmName,
         postData = this.jqGrid('getGridParam', 'postData'),
         columnsState = {
             search: this.jqGrid('getGridParam', 'search'),
             page: this.jqGrid('getGridParam', 'page'),
             sortname: this.jqGrid('getGridParam', 'sortname'),
             sortorder: this.jqGrid('getGridParam', 'sortorder'),
             rowNum: this.jqGrid('getGridParam', 'rowNum'),
             permutation: perm,
             colStates: {}
         },
         colStates = columnsState.colStates;

         if (typeof (postData.filters) !== 'undefined') {
             columnsState.filters = postData.filters;
         }

         for (i = 0; i < l; i++) {
             colItem = colModel[i];
             cmName = colItem.name;
             if (cmName !== 'rn' && cmName !== 'cb' && cmName !== 'subgrid') {
                 colStates[cmName] = {
                     width: colItem.width,
                     hidden: colItem.hidden
                 };
             }
         }
         saveObjectInLocalStorage(myColumnStateName($grid), columnsState);
     },
     myColumnsState,
     isColState,
     restoreColumnState = function (colModel) {
         var colItem, i, l = colModel.length, colStates, cmName,
         columnsState = getObjectFromLocalStorage(myColumnStateName($grid));

         if (columnsState) {
             colStates = columnsState.colStates;
             for (i = 0; i < l; i++) {
                 colItem = colModel[i];
                 cmName = colItem.name;
                 if (cmName !== 'rn' && cmName !== 'cb' && cmName !== 'subgrid') {
                     colModel[i] = $.extend(true, {}, colModel[i], colStates[cmName]);
                 }
             }
         }
         return columnsState;
    },
    firstLoad = true;

    myColumnsState = restoreColumnState(cm);
    isColState = typeof (myColumnsState) !== 'undefined' && myColumnsState !== null;

    $grid.bind('SaveSettings', function() { saveColumnState.call($grid, $grid.jqGrid('getGridParam', 'remapColumns')); });
    $grid.jqGrid({url: '/Databind/',
        datatype: 'json',
        mtype: 'GET',
        height: '100%', 
        width: 940, 
        shrinkToFit: false, 
        colModel: cm,
        rowNum: isColState ? myColumnsState.rowNum : 15,
        rowList: [5,10,15,30,50],
        pager: $('#gridPager'),
        page: isColState ? myColumnsState.page : 1,
        sortname: isColState ? myColumnsState.sortname : 'BillingRecordId',
        sortorder: isColState ? myColumnsState.sortorder : 'asc',
        search: isColState ? myColumnsState.search : false,
        viewrecords: true,
        loadComplete: function () {
            if (firstLoad) {
                firstLoad = false;
                if (isColState) {
                    $(this).jqGrid('remapColumns', myColumnsState.permutation, true);
                }
             }
             saveColumnState.call($(this), this.p.remapColumns);

             if($(this).jqGrid('getGridParam', 'page') > $(this).jqGrid('getGridParam', 'lastpage')) {
                 alert('reloading'); //this message shows
                 $(this).trigger('reloadGrid', [{ page: 1}]); //this doens't refresh the grid
              }

          }
     }).navGrid('#gridPager', { edit: false, add: false, del: false, refresh: false, search: false });

    $grid.jqGrid('navButtonAdd', '#gridPager', {
        buttonicon: 'ui-icon-closethick',
        caption: 'Reset Settings',
        title: 'Reset Settings',
        onClickButton: function () {
            removeObjectFromLocalStorage(myColumnStateName($grid));
            $grid.unbind('SaveSettings');
            window.location.reload();
        }
    });

    $grid.jqGrid('navButtonAdd', '#gridPager', {
        buttonicon: 'ui-icon-transferthick-e-w',
        caption: 'Choose Columns',
        title: 'Choose Columns',
        onClickButton: function () {
            $(this).jqGrid('columnChooser', {
                done: function (perm) {
                    if (perm) {
                        this.jqGrid('remapColumns', perm, true);
                        saveColumnState.call(this, perm);
                    }
                 }  
             });
         }
     });
});

$(window).unload( function () { $('#grid').trigger('SaveSettings'); });

I have read around and cannot find a solution. I have tried moving the trigger.('reloadGrid') into the gridComplete function but it doesn't work either. Always the alert message shows but the grid is not refreshed.

Upvotes: 2

Views: 9829

Answers (2)

Mark Rucker
Mark Rucker

Reputation: 8085

Intro

This works with jqGrid javascript version 4.4.4.

The primary problem is that reloadGrid doesn't work when we want it to. To understand why I'll explain everything I've learned today about reloadGrid. If none of that is of interest feel free to skip to the solution.

How reloadGrid Works

reloadGrid has the following pseudocode:

  1. Run preprocessing logic for treeGrids
  2. Run preprocessing logic for multiselects
  3. Run preprocessing logic for page logic and scroll logic
  4. Populate the grid's data (by calling either populate() or populateVisible())

Both populate and populateVisible have identical pseudo code:

  1. Check an internal variable, loading, if (loading) { return; } else {/*load data*/}
  2. Run preprocessing for paging and grouping
  3. Set loading = true
  4. load the data into memory (depending on datatype either by ajax or from a string or locally)
  5. populate the grid with the loaded memory
  6. Set loading = false

How To Solve This

I can't imagine having a problem without ajax. Therefore, I'm going to just focus on ajax.

The grid provides lots of helpful events we can hook into during the ajax process. Unfortunately, all of the jqGrid events we can hook into occur before step 6. This means that loading always equals true when our events handlers are triggered. Because loading is false reloadGrid won't do anything when it calls out to populate().

To get around this we need to be able to inject our logic for reloading into a location after loading has been set to false. The easiest way I've found to do this is to inject our logic into the ajax complete event. For the given question above it would look like the following.

function reloadGridIfPageIsBeyondLast() {
    if($(this).jqGrid('getGridParam', 'page') > $(this).jqGrid('getGridParam', 'lastpage')) {
        $(this).trigger('reloadGrid', [{ page: 1}]);
    }
}

$('#grid').jqGrid('setGridParam', { 
    ajaxGridOptions: {
        complete: reloadJqGridIfPagePastLast
    }
}

Upvotes: 0

Random Developer
Random Developer

Reputation: 175

I found a workaround, it is not perfect though. If I use setTimeout to add a delay to the reload call, everything works. I added an additional check to make sure the lastPage is over 0 otherwise empty grids will constantly reload.

loadComplete: function () {
    if (firstLoad) {
        firstLoad = false;
        if (isColState) {
            $(this).jqGrid('remapColumns', myColumnsState.permutation, true);
        }
    }
    saveColumnState.call($(this), this.p.remapColumns);

    var lastPage = $(this).jqGrid('getGridParam', 'lastpage');
    var page = $(this).jqGrid('getGridParam', 'page');
    if(lastPage > 0 && page > lastPage) {                    
        setTimeout(function () { $('#grid').trigger('reloadGrid', [{ page: 1}]); },150);
    }
}

Upvotes: 4

Related Questions