jqGrid: using beforeProcessing to populate filterToolbar selection boxes

I am populating three dropdown boxes in my filterToolbar with data from the server, shown in the declaration of prodValues, envValues, and typeValues below. I would like to change my code to perform this operation in the beforeProcessing event and pull the values from the main grid data dump. I already have the server sending what I think is the proper json response to do this:

{
   "pVals":"Product1:Product1;Product2:Product2;etc:etc",
   "eVals":"??:??;Dev:Dev;PreProd:PreProd;Prod:Prod;Test/QA:Test/QA",
   "tVals":"??:??;App:App;Service:Service;SQL:SQL;Web:Web",
   "page":0,
   "total":0,
   "records":537,
   "rows":[ /* many rows */
    ]
}

How can I pick out the pVals, eVals, and tVals strings in the beforeProcessing event and stick them into the corresponding filterToolbar selection boxes?

Here is my grid code for reference, with my broken attempts to solve this problem commented out:

$(function () {
            var grid = $("#PSGrid");

            var pVals, eVals, tVals;

            // get values from Products table
            var prodValues = $.ajax({
                url: "jqGridHandler.ashx?oper=pVals",
                async: false,
                success: function (data) {

                }
            }).responseText;

            // get values from Environments table
            var envValues = $.ajax({
                url: "jqGridHandler.ashx?oper=eVals",
                async: false,
                success: function (data) {

                }
            }).responseText;

            // get values from ServerTypes table
            var typeValues = $.ajax({
                url: "jqGridHandler.ashx?oper=tVals",
                async: false,
                success: function (data) {

                }
            }).responseText;

            var lastsel = -1;

            // build the grid
            grid.jqGrid({
                url: 'jqGridHandler.ashx',
                editurl: 'jqGridEditor.ashx',
                datatype: 'json',
                height: 550,
                width: 'auto',
                colNames: ['ID', 'Product', 'Environment', 'Hostname', 'IP', 'Description', 'Type', 'PortsUsed', 'DeletedFlag', 'Decommissioned', 'User'],
                colModel: [
                    { name: 'ID', index: 'ID', width: 50, sortable: true, hidden: true, editable: false, key: true, sorttype: 'int' },
                    {
                        name: 'Product', index: 'Product', width: 125, sortable: true, editable: true,
                        stype: 'select', searchoptions: { value: ':All;' + prodValues, sopt: ['eq'] },
                        formatter: 'select', edittype: 'select', editoptions: { value: prodValues },
                        editrules: { required: true }
                    },
                    {
                        name: 'Environment', index: 'Environment', width: 100, sortable: true, editable: true,
                        stype: 'select', searchoptions: { value: ':All;' + envValues, sopt: ['eq'] },
                        formatter: 'select', edittype: 'select', editoptions: { value: envValues },
                        editrules: { required: true }
                    },
                    {
                        name: 'Hostname', index: 'Hostname', width: 200, sortable: true, editable: true,
                        editrules: { required: true }
                    },
                    {
                        name: 'IP', index: 'IP', width: 125, sortable: false, editable: true
                    },
                    {
                        name: 'Description', index: 'Description', width: 200, sortable: true, editable: true,
                        editrules: { required: true }
                    },
                    {
                        name: 'Type', index: 'Type', width: 75, sortable: true, editable: true,
                        stype: 'select', searchoptions: { value: ':All;' + typeValues, sopt: ['eq'] },
                        formatter: 'select', edittype: 'select', editoptions: { value: typeValues },
                        editrules: { required: true }
                    },
                    { name: 'PortsUsed', index: 'PortsUsed', width: 80, sortable: false, editable: true },
                    { name: 'DeletedFlag', index: 'DeletedFlag', hidden: true, searchoptions: { sopt: ['eq'], searchhidden: true }},
                    {
                        name: 'Decommissioned', index: 'DeletedFlag', width: 150, sortable: false, editable: false,
                        stype: 'select', searchoptions: { value: 'FALSE:No;TRUE:Yes' }/*, sorttype: 'date', datefmt: 'M/d/Y H:i:s A'*/
                    },
                    { name: 'User', index: 'User', width: 75, sortable: true, editable: false }
                ],
                rowNum: 10000, // show all rows hack (-1 is the proper way to do it but is bugged in this version of jqGrid)
                pager: '#PSGridPager',
                sortname: 'ID',
                pgbuttons: false,
                pgtext: null,
                viewrecords: false,
                sortorder: 'asc',
                ignoreCase: true,
                caption: 'Click a row to edit.  [Enter] to save, [Esc] to cancel.',
                loadonce: true,
                /*jsonReader: {
                    pVals: "pVals",
                    eVals: "eVals",
                    tVals: "tVals"
                },*/
                onSelectRow: function (id) {
                    if (id && id !== lastsel) {
                        grid.jqGrid('restoreRow', lastsel);
                        lastsel = id;
                    }
                    grid.jqGrid('editRow', id, true);
                },

                /*beforeProcessing: function (data) {
                    var pVals = data.pVals;
                    grid.setColProp('Product', {
                        index: 'Product', width: 125, sortable: true, editable: true,
                        stype: 'select', searchoptions: { value: ':All;' + pVals, sopt: ['eq'] },
                        formatter: 'select', edittype: 'select', editoptions: { value: pVals },
                        editrules: { required: true }
                    });
                }*/
            });

            grid.jqGrid('filterToolbar', { stringResult: true, searchOnEnter: true, defaultSearch: "cn" });
            grid.jqGrid('navGrid', '#PSGridPager', { edit: false, add: true, del: true, search: false, refresh: true, paging: false },
                { /* edit options */ },
                { /* add options */
                    closeOnEscape: true,
                    closeAfterAdd: true,
                    reloadAfterSubmit: true,
                    width: 400
                },
                { /* delete options */
                    closeOnEscape: true,
                    reloadAfterSubmit: true
                });
            grid.jqGrid('navButtonAdd', '#PSGridPager', {
                caption: "Export to Excel",
                onClickButton: function () {
                    grid.jqGrid('excelExport', { url: "jqGridHandler.ashx" });
                }
            });
        });

If I try to use beforeProcessing as is, the Product column does not display a filter and shows no data.


Solution 1:

It seems to me that you use already almost correct code. The most problem is that you need refresh existing filter toolbar. You can use destroyFilterToolbar method which I suggested in the answer. I suggested it later to trirand (see here and the pull request) and it's included in the main code of jqGrid now. Your code can be like below.

beforeProcessing: function (data) {
    var $self = $(this),
        newProductValues = data.pVals,
        newEnvironmentValues = data.eVals,
        newTypeValues = data.tVals,
        cmProduct = $self.jqGrid("getColProp, "Product"),
        cmEnvironment = $self.jqGrid("getColProp, "Environment"),
        cmType = $self.jqGrid("getColProp", "Type"),
        isChanged = false;

    if (cmProduct.editoptions.value !== newProductValues) {
        $self.jqGrid("setColProp", "Product", {
            searchoptions: { value: ":All;" + newProductValues },
            editoptions: { value: newProductValues }
        });
        isChanged = true;
    }
    if (cmEnvironment.editoptions.value !== newEnvironmentValues) {
        $self.jqGrid("setColProp", "Environment", {
            searchoptions: { value: ":All;" + newEnvironmentValues },
            editoptions: { value: newEnvironmentValues }
        });
        isChanged = true;
    }
    if (cmType.editoptions.value !== newTypeValues) {
        $self.jqGrid("setColProp", "Environment", {
            searchoptions: { value: ":All;" + newTypeValues },
            editoptions: { value: newTypeValues }
        });
        isChanged = true;
    }
    if (isChanged) {
        // recreate filter toolbar to refresh the data
        $self.jqGrid("destroyFilterToolbar");
        $self.jqGrid("filterToolbar", {
            stringResult: true,
            searchOnEnter: true,
            searchOperators: true,
            defaultSearch: "cn"
        });
    }
}

(I included new searchOperators: true option which could be intresting)

You can combine the solution with the call of the function refreshSerchingToolbar which I described in the answer to load old filter in the filter toolbar.

By the way you can consider to change format of value property which you use. Instead of usage string form "Product1:Product1;Product2:Product2;etc:etc" you can use object form {Product1: "Product1", Product2:"Product2", etc: "etc"}.