且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

jqGrid将多选择列过滤器添加到特定列

更新时间:2023-11-24 16:04:04

从其他问题中,您可以看到您使用了免费的jqGrid fork.它支持自动生成唯一值.这样一个人就可以使用

From your other questions one can see that you use free jqGrid fork. It supports generating of unique values automatically. Thus one can use

searchoptions: {
    generateValue: true,
    sopt: ["in"],
    attr: { multiple: "multiple", size: 7 },
    dataInit: dataInitMultiselect
}

代替

searchoptions: {
    clearSearch: false,
    sopt: ['eq', 'ne'],
    value: buildSearchSelect(getUniqueNames(columnName, data,grid)),
    attr: { multiple: 'multiple', size: 7},
    dataInit: dataInitMultiselect
}

重要的是,仅在加载数据后才填充列中数据的唯一值.然后,应该在从服务器加载数据后创建或重新创建filterToolbar.例如,可以在loadComplete内部测试this.ftoolbar来检测filterToolbar是否已经存在:

It's important that unique values of data in the column will be filled only after loading the data. Then one should create or recreate filterToolbar after loading the data from the server. One can test this.ftoolbar inside of loadComplete for example to detect whether filterToolbar already exist:

loadComplete: function () {
    if (!this.ftoolbar) {
        // create filter toolbar if it isn't exist 
        $(this).jqGrid("filterToolbar", {
            defaultSearch: "cn",
            beforeClear: function() {
                $(this.grid.hDiv)
                    .find(".ui-search-toolbar button.ui-multiselect")
                    .each(function() {
                    $(this).prev("select[multiple]").multiselect("refresh");
                });
            }
        });
        $(this).triggerHandler("jqGridRefreshFilterValues");
        $(this.grid.hDiv)
            .find(".ui-search-toolbar button.ui-multiselect")
            .each(function() {
            $(this).prev("select[multiple]")
                .multiselect("refresh");
        });        
    }
}

演示 https://jsfiddle.net/OlegKi/ty4e68pm/2/显示了在免费jqGrid中使用multiselect的可能实现.函数dataInitMultiselect具有以下实现:

The demo https://jsfiddle.net/OlegKi/ty4e68pm/2/ shows a possible implementation of usage multiselect in free jqGrid. The function dataInitMultiselect has the following implementation:

var dataInitMultiselect = function (elem, searchOptions) {
        var $grid = $(this);
        setTimeout(function() {
            var $elem = $(elem),
                id = elem.id,
                inToolbar = searchOptions.mode === "filter",
                options = {
                    selectedList: 2,
                    height: "auto",
                    checkAllText: "all",
                    uncheckAllText: "no",
                    noneSelectedText: "Any",
                    open: function() {
                        var $menu = $(".ui-multiselect-menu:visible");
                        $menu.width("auto");
                    }
                },
                $options = $elem.find("option");
            if ($options.length > 0 && $options[0].selected) {
                $options[0].selected = false; // unselect the first selected option

            }
            if (inToolbar) {
                options.minWidth = "auto";
            }
            $grid.triggerHandler("jqGridRefreshFilterValues");
            $elem.multiselect(options);
            // replace icons ui-icon-check, ui-icon-closethick, ui-icon-circle-close
            // and ui-icon-triangle-1-s to font awesome icons
            var $header = $elem.data("echMultiselect").header;
            $header.find("span.ui-icon.ui-icon-check")
                .removeClass("ui-icon ui-icon-check")
                .addClass("fa fa-fw fa-check");
            $header.find("span.ui-icon.ui-icon-closethick")
                .removeClass("ui-icon ui-icon-closethick")
                .addClass("fa fa-fw fa-times");
            $header.find("span.ui-icon.ui-icon-circle-close")
                .removeClass("ui-icon ui-icon-circle-close")
                .addClass("fa fa-times-circle");
            $elem.data("echMultiselect")
                .button
                .find("span.ui-icon.ui-icon-triangle-1-s")
                .removeClass("ui-icon ui-icon-triangle-1-s")
                .addClass("fa fa-caret-down")
                .css({
                    float: "right",
                    marginRight: "5px"
                });

            $elem.siblings("button.ui-multiselect").css({
                width: "100%",
                margin: "1px 0",
                paddingTop: ".3em",
                paddingBottom: ".3em"
            });
        }, 50);
    };

更新:我分析了您的演示 https://jsfiddle.net /B_AV_B/7ecrmtz4/5/.它包含很多错误:

UPDATED: I analysed your demo https://jsfiddle.net/B_AV_B/7ecrmtz4/5/. It contains a lot of error:

  1. 您在多选列中缺少stype : "select".搜索字段必须具有选择类型(stype : "select")才能显示为<select>元素,以后可以根据多选控件进行转换
  2. 我多次写信给您,内容涉及仅插入一个版本的jQuery和其他JavaScript库的重要性.此外,根据依赖关系保持插入的JS文件的顺序很重要. Multiselect小部件是jQuery UI的插件.因此,必须先插入jQuery UI.简而言之,您应该替换
  1. you missing stype : "select" in multiselect column. The searching field have to have select type (stype : "select") to be able to be displayed as <select> alement, which can be converted later with respect of multiselect control
  2. I wrote you multiple times about importance inserting only one version of jQuery and other JavaScript libraries. Moreover, it's important to hold the order of inserted JS files based on dependencies. Multiselect widget is plugin to jQuery UI. Thus jQuery UI must be inserted before. In short you should replace

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ui-multiselect-widget/2.0.2/jquery.multiselect.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>   

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-ui-multiselect-widget/2.0.2/jquery.multiselect.js"></script>

  1. 您应删除../bootstrap-multiselect/0.9.13/js/bootstrap-multiselect.js,此覆盖 multiselect先前已注册.
  2. JavaScript区分大小写.似乎输入数据的ID属性指定了每个输入项的唯一ID.默认情况下,jqGrid使用id而不是ID.如果使用datatype: "local",则应包括localReader: { id: "ID" }参数.如果使用datatype: "json",则应包括jsonReader: { id: "ID" }.您可以同时包含两个参数.
  3. 您在open回调中使用了错误的代码(将您的代码与我的答案中的代码进行比较).无需其他操作即可将其用作var $menu = $(".ui-multiselect-menu:visible"); $menu.width("auto");就足够了,这使得其他一些项目不可见.
  4. colModelwidth属性的值应该是数字,而不是像"120%"这样的字符串.数字将被解释为像素.如果使用autowidth : true,则初始width值将按比例增加,以使网格的宽度等于外部元素的宽度.
  5. 最后,我在您的演示中添加了一些CSS规则
  1. You should remove ../bootstrap-multiselect/0.9.13/js/bootstrap-multiselect.js, which overwrite multiselect registered previously.
  2. JavaScript is case sensitive. It seems that ID property of input data specifies unique id of every input item. jqGrid uses id instead of ID by default. If you use datatype: "local" then you should include localReader: { id: "ID" } parameter. If you use datatype: "json" then you should include jsonReader: { id: "ID" }. In your case you can include both parameters.
  3. You used wrong code of open callback (compare your code, with the code from my answer). It's enough to use it as var $menu = $(".ui-multiselect-menu:visible"); $menu.width("auto"); without additional actions, which makes some other items invisible.
  4. Values of width property on colModel should be numbers and not strings like "120%". Numbers will be interpreted as pixels. If you use autowidth : true the initial width values will be proportionally increased to make the width of the grid equal to the width of outer element.
  5. Finally I added some CSS rules to your demo

.ui-multiselect-menu .ui-multiselect-header ul,
.ui-multiselect-menu .ui-multiselect-checkboxes li {
    font-size: 12px;
}

.ui-multiselect-menu .ui-multiselect-header a:hover {
    text-decoration: none;
}
.ui-multiselect-menu .ui-multiselect-close {
    margin-right: 3px;
}

您可以根据您的要求修改上述规则上的font-size.

You can modify the font-size on the above rule corresponds to your requirements.

修改后的演示为 https://jsfiddle.net/OlegKi/teLja6z3/25/