jqGrid:动态重建搜索过滤器选项

时间:2014-05-22 14:23:10

标签: jquery jqgrid

我有一个jqGrid,它使用AJAX(在MVC中)从数据库中获取数据。行和列是动态的,并根据用户从jqGrid上方的选择列表中选择的内容进行更改。每列都有一个下拉列表框来过滤行。

一切都运行良好:返回数据,动态构建列和搜索过滤器,过滤器可以正常工作。但有一个问题:

如果我使用其搜索过滤器下拉列表过滤列,则在过滤行后,其他列中的下拉过滤器仍包含与当前结果集不再相关的原始选项 - 例如< / p>

在我未过滤的专栏中,我在过滤结果中可能只有以下国家/地区:

  • 英格兰
  • 法国
  • 意大利

但该列的搜索过滤器仍包含所有国家/地区,即使它们不再与用户相关:

  • 奥地利
  • 澳大利亚
  • 比利时
  • ...
  • 英国
  • 法国
  • 意大利
  • ...
  • 台湾
  • 美国

我希望任何过滤器下拉列表中没有应用过滤器的选项只包含与结果集相关的选项 - 在这种情况下:英格兰,法国,意大利。 < / p>

这可能吗?我尝试在搜索选项中设置recreateFilter:true,但它没有任何区别。

这是我第一次使用jqGrid,所以我从网上拼凑了很多代码,如果它可以帮助任何人回答我的问题,我会在这里发布。有一点需要注意,我正在使用jqGrid 4.3.2,因为我无法获得更高版本的工作。无论如何,这是代码和感谢阅读!

grid = $("#list");
grid.jqGrid({
            jsonReader: { repeatitems: true, root: "rows", page: "page", total: "total", records: "records" },
            url: '@Url.Content("~/DocumentSearch/GetData?keywordSearch=")' + keywords + '&documentTypeId=' + documentTypeId,
            datatype: 'json',
            mtype: 'GET',
            colModel: buildColumnModel(columns),
            rowList: [5, 10, 20, 50],
            viewrecords: true,
            height: 'auto',
            autowidth: true,
            loadonce: true,
            shrinktofit: true,
            rowNum: 10000,
            autoencode: true,
            autowidth: true,

            afterInsertRow: function (rowid, rowdata, rowelem) {
                $(this).attr("data-toggle", "modal");
                $(this).attr("data-target", ".bs-example-modal-sm");
            },
            beforeRequest: function () {
                var separator = ',';

                var i, l, rules, rule, parts, j, group, str, iCol, cmi, cm = this.p.colModel,
                                filters = $.parseJSON(this.p.postData.filters);


                if (filters && typeof filters.rules !== 'undefined' && filters.rules.length > 0) {
                    rules = filters.rules;

                    for (i = 0; i < rules.length; i++) {
                        rule = rules[i];
                        iCol = getColumnIndexByName.call(this, rule.field);
                        cmi = cm[iCol];


                        if (iCol >= 0 && ((typeof (cmi.searchoptions) === "undefined" ||
                                          typeof (cmi.searchoptions.sopt) === "undefined")
                                         && rule.op === myDefaultSearch) ||
                                            (typeof (cmi.searchoptions) === "object" &&
                                                $.isArray(cmi.searchoptions.sopt) &&
                                                cmi.searchoptions.sopt[0] === rule.op)) {


                            // make modifications only for the 'contains' operation
                            parts = rule.data.split(separator);

                            if (parts.length > 1) {
                                if (typeof filters.groups === 'undefined') {
                                    filters.groups = [];
                                }
                                group = {
                                    groupOp: 'OR',
                                    groups: [],
                                    rules: []
                                };

                                filters.groups.push(group);
                                for (j = 0, l = parts.length; j < l; j++) {
                                    str = parts[j];
                                    if (str) {
                                        // skip empty '', which exist in case of two separaters of once
                                        group.rules.push({
                                            data: parts[j],
                                            op: rule.op,
                                            field: rule.field
                                        });
                                    }
                                }
                                rules.splice(i, 1);
                                i--; // to skip i++
                            }
                        }
                    }

                    this.p.postData.filters = JSON.stringify(filters);
                }
            }
            , loadComplete: function (data) {
                var columnNamesArr = columns.split(',');
                for (i = 0; i < columnNamesArr.length; i++) {
                    setSearchSelect(columnNamesArr[i]);
                }

                grid.jqGrid('filterToolbar', {
                    search: true, searchOnEnter: true, autosearch: true, defaultSearch: myDefaultSearch
                });

                if (data != null && data.records != null) {
                    $("#recordCount").text(data.records.toString());
                }

                grid.trigger("reloadGrid");
            }
        });
    }



    function buildColumnModel(columns) {
        var uFields = columns.split(',');
        var columns = [];
        for (var i = 0; i < uFields.length; i++) {
            if (uFields[i].indexOf('Id') > -1) {
                columns.push({ name: uFields[i], index: uFields[i], hidden: true });
            }
            else {
                columns.push({ name: uFields[i], index: uFields[i] });
            }
        }

        return columns;
    }

    function setSearchSelect(columnName) {
        grid.jqGrid('setColProp', columnName, {
            stype: 'select',
            searchoptions: {
                sopt: ['eq', 'ne'],

                multipleSearch: true,
                multipleGroup: true,
                recreateFilter: true,
                closeOnEscape: true,
                closeAfterSearch: true,

                value: buildSearchSelect(getUniqueNames(columnName))
                , attr: { multiple: 'multiple', size: 2 }
                , dataInit: function (elem) {
                    setTimeout(function () {
                        $(elem).multiselect({
                            minWidth: 100,
                            height: "auto",
                            selectedList: 4,
                            checkAllText: "all",
                            uncheckAllText: "clear",
                            noneSelectedText: "All",
                            open: function () {
                                var $menu = $(".ui-multiselect-menu:visible");
                                $menu.width("auto");
                                return;
                            }
                        });
                    }, 50);
                }
            }
        });
    }

    function buildSearchSelect(uniqueNames) {
        var values = '';
        $.each(uniqueNames, function () {
            if (this.length > 0) {
                values += this + ":" + this + ";";
            }
        });

        if (values != null) {
            values = values.substr(0, values.length - 1);
        }

        return values;
    }

    function getUniqueNames(columnName) {
        var texts = grid.jqGrid('getCol', columnName);
        var uniqueTexts = [];
        var textsLength = texts.length;
        var text;
        var textsMap = {};
        var i;

        for (i = 0; i < textsLength; i++) {
            text = texts[i];
            if (text !== undefined && textsMap[text] === undefined) {
                // to test whether the texts is unique we place it in the map.
                textsMap[text] = true;
                uniqueTexts.push(text);
            }
        }

        uniqueTexts.sort();
        return uniqueTexts;
    }

2 个答案:

答案 0 :(得分:2)

我通过在searchOptions上挂钩dataEvents解决了这个问题,据我所知,在过滤器下拉列表的更改事件期间调用了它。我不得不重建每个列的过滤器下拉列表中的唯一值,然后重建每个html选择:

function setSearchSelect(columnName) {
    grid.jqGrid('setColProp', columnName, {
        stype: 'select',
        searchoptions: {
            sopt: ['eq', 'ne'],
            value: buildSearchSelect(getUniqueNames(columnName))
            , attr: { multiple: 'multiple', size: 2 }
            , dataInit: function (elem) {
                setTimeout(function () {
                    $(elem).multiselect({
                        minWidth: 100,
                        height: "auto",
                        selectedList: 4,
                        checkAllText: "all",
                        uncheckAllText: "clear",
                        noneSelectedText: "All",
                        open: function () {
                            var $menu = $(".ui-multiselect-menu:visible");
                            $menu.width("auto");
                            return;
                        }
                    });
                }, 50);
            }
            , dataEvents: [
                {
                    type: "change",
                    fn: function (e) {
                        setTimeout(function () {
                            var columnNamesArr = columns.split(',');

                            for (i = 0; i < columnNamesArr.length; i++) {
                                if (columnNamesArr[i].toString() != columnName) {
                                    htmlForSelect = ""; // = '<option value="">All</option>';
                                    var un = getUniqueNames(columnNamesArr[i]);
                                    var $select = $("select[id='gs_" + columnNamesArr[i] + "']");

                                    for (j = 0; j < un.length; j++) {
                                        val = un[j];

                                        htmlForSelect += '<option value="' + val + '">' + val + '</option>';
                                    }

                                    $select.find('option').remove().end().append(htmlForSelect);

                                    $select.multiselect('refresh');

                                    setTimeout(function () {
                                        $select.multiselect('destroy').multiselect({
                                            minWidth: 100,
                                            height: "auto",
                                            selectedList: 4,
                                            checkAllText: "all",
                                            uncheckAllText: "clear",
                                            noneSelectedText: "All",
                                            open: function () {
                                                var $menu = $(".ui-multiselect-menu:visible");
                                                $menu.width("auto");
                                                return;
                                            }
                                        });
                                    }, 50);
                                }
                            }
                        }, 500);
                    }
                }
            ]
        }
    });
}

如果您对此有任何疑问,我会尽力回答。

答案 1 :(得分:0)

这是一个基于

的完整工作样本

documentation

和上面的帖子

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>http://stackoverflow.com/questions/5543902/change-filtertoolbar-options-dynamically</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

    <!--link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/redmond/jquery-ui.css" />
    <link rel="stylesheet" type="text/css" href="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-3.8.2/src/css/ui.jqgrid.css" /-->
    <!--script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"></script>
    <script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-3.8.2/js/i18n/grid.locale-en.js"></script>
    <script type="text/javascript" src="http://www.ok-soft-gmbh.com/jqGrid/jquery.jqGrid-3.8.2/js/jquery.jqGrid.min.js"></script-->

    <script type="text/javascript" src="./jqGrid/js/jquery.min.js"></script>
    <script type="text/javascript" src="./jqGrid/js/jquery-ui.min.js"></script>
    <!-- The Context Menu 3rd party plugin that we are using  -->
    <script type="text/javascript" src="./jqGrid/js/context-menu.js"></script>
    <!-- This is the Javascript file of jqGrid -->   
    <script type="text/javascript" src="./jqGrid/js/trirand/jquery.jqGrid.min.js"></script>
    <!-- This is the localization file of the grid controlling messages, labels, etc.-->
    <!-- We support more than 40 localizations -->
    <script type="text/javascript" src="./jqGrid/js/trirand/i18n/grid.locale-en.js"></script>
    <!-- A link to a jQuery UI theme, more than 25 custom  -->
    <link rel="stylesheet" type="text/css" media="screen" href="./jqGrid/themes/overcast/jquery-ui.css" />
    <!--link rel="stylesheet" type="text/css" media="screen" href="./jqGrid/jquery-ui-1.12.1.custom/jquery-ui.css" /-->
    <!-- The link to the CSS that the grid needs -->
    <link rel="stylesheet" type="text/css" media="screen" href="./jqGrid/css/trirand/ui.jqgrid.css?ver=030220181637" />


    <script type="text/javascript" src="js/multiselect/multiselect.js"></script>

    <script type="text/javascript">
    //<![CDATA[
        $(document).ready(function() 
        {
            var mygrid = $("#list"),
                pagerSelector = "#pager",
                mydata = [
                   {id:"1",invdate:"2007-10-01",name:"abc",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
                   {id:"2",invdate:"2007-10-02",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
                   {id:"3",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
                   {id:"4",invdate:"2007-10-04",name:"def",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
                   {id:"5",invdate:"2007-10-05",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
                   {id:"6",invdate:"2007-09-06",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
                   {id:"7",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
                   {id:"8",invdate:"2007-10-03",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
                   {id:"9",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
                   {id:"10",invdate:"2007-10-01",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
                   {id:"11",invdate:"2007-10-02",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
                   {id:"12",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
                   {id:"13",invdate:"2007-10-04",name:"test",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
                   {id:"14",invdate:"2007-10-05",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
                   {id:"15",invdate:"2007-09-06",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"},
                   {id:"16",invdate:"2007-10-04",name:"xyz",note:"note",amount:"200.00",tax:"10.00",total:"210.00"},
                   {id:"17",invdate:"2007-10-03",name:"test2",note:"note2",amount:"300.00",tax:"20.00",total:"320.00"},
                   {id:"18",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"}
                ];
                columns = "id,invdate,name,amount,tax,total,note";

            function getColumnIndexByName(mygrid, columnName) 
            {
                var cm = $("#list").jqGrid('getGridParam', 'colModel');
                for (var i = 0, l = cm.length; i < l; i++) 
                {
                    if (cm[i].name === columnName) 
                    {
                        return i;
                    }
                }
                return -1;
            };

            $("#list").jqGrid({
                datatype: 'local',
                data: mydata,
                colNames:['Inv No','Date', 'Client', 'Amount','Tax','Total','Notes'],
                colModel: buildColumnModel(columns),
                height: '100%',
                width: 720,
                toppager: true,
                gridview: true,
                pager: pagerSelector,
                rowNum: 10,
                rowList: [5, 10, 20, 50],
                sortname: 'id',
                sortorder: 'asc',
                viewrecords: true,
                caption: 'Add buttons to both top and bottom toolbars',
                afterInsertRow: function (rowid, rowdata, rowelem) {
                $(this).attr("data-toggle", "modal");
                $(this).attr("data-target", ".bs-example-modal-sm");
            },
            beforeRequest: function () {
                var separator = ',';

                var i, l, rules, rule, parts, j, group, str, iCol, cmi;

                console.log("filter:" + this.p.postData.filters);
                var cm = this.p.colModel, filters;

                if (this.p.postData.filters && this.p.postData.filters !== 'undefined')
                    filters =  $.parseJSON(this.p.postData.filters);

                if (filters && typeof filters.rules !== 'undefined' && filters.rules.length > 0) {
                    rules = filters.rules;

                    for (i = 0; i < rules.length; i++) {
                        rule = rules[i];
                        iCol = getColumnIndexByName.call(this, rule.field);
                        cmi = cm[iCol];


                        if (iCol >= 0 && ((typeof (cmi.searchoptions) === "undefined" ||
                                          typeof (cmi.searchoptions.sopt) === "undefined")
                                         && rule.op === 'cn') /*||
                                            (typeof (cmi.searchoptions) === "object" &&
                                                $.isArray(cmi.searchoptions.sopt) &&
                                                cmi.searchoptions.sopt[0] === rule.op)*/) {


                            // make modifications only for the 'contains' operation
                            parts = rule.data.split(separator);

                            if (parts.length > 1) {
                                if (typeof filters.groups === 'undefined') {
                                    filters.groups = [];
                                }
                                group = {
                                    groupOp: 'OR',
                                    groups: [],
                                    rules: []
                                };

                                filters.groups.push(group);
                                for (j = 0, l = parts.length; j < l; j++) {
                                    str = parts[j];
                                    if (str) {
                                        // skip empty '', which exist in case of two separaters of once
                                        group.rules.push({
                                            data: parts[j],
                                            op: rule.op,
                                            field: rule.field
                                        });
                                    }
                                }
                                rules.splice(i, 1);
                                i--; // to skip i++
                            }
                        }
                    }

                    this.p.postData.filters = JSON.stringify(filters);
                }
            }
            , loadComplete: function (data) {
                var columnNamesArr = columns.split(',');
                for (i = 0; i < columnNamesArr.length; i++) {
                    setSearchSelect(columnNamesArr[i]);
                }

                $("#list").jqGrid('filterToolbar', {
                    search: true, searchOnEnter: true, autosearch: true, defaultSearch: 'cn'
                });

                if (data != null && data.records != null) {
                    $("#recordCount").text(data.records.toString());
                }

                $("#list").trigger("reloadGrid");
            }
            });
            $("#list").jqGrid('filterToolbar',
                          {stringResult:true, searchOnEnter:true, defaultSearch:'cn'});
            $("#setbw").click(function() {
                $("#list").jqGrid('setColProp','name',{searchoptions:{sopt:['bw']}});
            });
            $("#setew").click(function() {
                $("#list").jqGrid('setColProp','name',{searchoptions:{sopt:['ew']}});
            });


function buildColumnModel(columns) {
        var uFields = columns.split(',');
        var columns = [];
        for (var i = 0; i < uFields.length; i++) {
            if (uFields[i].indexOf('Id') > -1) {
                columns.push({ name: uFields[i], index: uFields[i], hidden: true });
            }
            else {
                columns.push({ name: uFields[i], index: uFields[i] });
            }
        }

        return columns;
    }

    function setSearchSelect(columnName) {
        mygrid.jqGrid('setColProp', columnName, {
        stype: 'select',
        searchoptions: {
            sopt: ['eq', 'ne'],
            value: buildSearchSelect(getUniqueNames(columnName))
            , attr: { multiple: 'multiple', size: 2 }
            , dataInit: function (elem) {
                setTimeout(function () {
                    $(elem).multiselect({
                        minWidth: 100,
                        height: "auto",
                        selectedList: 4,
                        checkAllText: "all",
                        uncheckAllText: "clear",
                        noneSelectedText: "All",
                        open: function () {
                            var $menu = $(".ui-multiselect-menu:visible");
                            $menu.width("auto");
                            return;
                        }
                    });
                }, 50);
            }
            , dataEvents: [
                {
                    type: "change",
                    fn: function (e) {
                        setTimeout(function () {
                            var columnNamesArr = columns.split(',');

                            for (i = 0; i < columnNamesArr.length; i++) {
                                if (columnNamesArr[i].toString() != columnName) {
                                    htmlForSelect = ""; // = '<option value="">All</option>';
                                    var un = getUniqueNames(columnNamesArr[i]);
                                    var $select = $("select[id='gs_" + columnNamesArr[i] + "']");

                                    for (j = 0; j < un.length; j++) {
                                        val = un[j];

                                        htmlForSelect += '<option value="' + val + '">' + val + '</option>';
                                    }

                                    $select.find('option').remove().end().append(htmlForSelect);

                                    $select.multiselect('refresh');

                                    setTimeout(function () {
                                        $select.multiselect('destroy').multiselect({
                                            minWidth: 100,
                                            height: "auto",
                                            selectedList: 4,
                                            checkAllText: "all",
                                            uncheckAllText: "clear",
                                            noneSelectedText: "All",
                                            open: function () {
                                                var $menu = $(".ui-multiselect-menu:visible");
                                                $menu.width("auto");
                                                return;
                                            }
                                        });
                                    }, 50);
                                }
                            }
                        }, 500);
                    }
                }
            ]
        }
        });
    }


    function buildSearchSelect(uniqueNames) {
        var values = '';
        $.each(uniqueNames, function () {
            if (this.length > 0) {
                values += this + ":" + this + ";";
            }
        });

        if (values != null) {
            values = values.substr(0, values.length - 1);
        }

        return values;
    }

    function getUniqueNames(columnName) {
        var texts = mygrid.jqGrid('getCol', columnName);
        var uniqueTexts = [];
        var textsLength = texts.length;
        var text;
        var textsMap = {};
        var i;

        for (i = 0; i < textsLength; i++) {
            text = texts[i];
            if (text !== undefined && textsMap[text] === undefined) {
                // to test whether the texts is unique we place it in the map.
                textsMap[text] = true;
                uniqueTexts.push(text);
            }
        }

        uniqueTexts.sort();
        return uniqueTexts;
    }        

        });
    //]]>
    </script>
</head>

<body>
<fieldset style="float:left">
<button id="setbw">Set on 'Client' search option to 'begin with'</button>
<button id="setew">Set on 'Client' search option to 'end with'</button>
</fieldset>
<div style="clear:left">
    <table id="list"><tbody><tr><td/></tr></tbody></table>
    <div id="pager"></div>
</div>

</body>
</html>