jqGrid добавить фильтр выбора нескольких столбцов в определенный столбец - PullRequest
1 голос
/ 10 июня 2019

Я пытаюсь добавить фильтр множественного выбора в мой столбец PROVIDER в jqGrid. Я могу добавить фильтр выбора, но теперь я конвертирую его в фильтр множественного выбора. Я сослался на несколько старых постов здесь и попытался сделать то же самое. Это не вызывает у меня никаких ошибок, но также не создает фильтр множественного выбора. Пожалуйста, дайте мне знать, что я делаю неправильно ниже. Я могу получить уникальные значения и создать список SELECT. Я предполагаю, что что-то не так с функцией dataInitMultiselect , потому что я пытался console.log (elem) , но это не так возвращая что-либо, даже не определенное, но функция вызывается, потому что она не выдает мне неопределенную ошибку функции.

$("#home_grid").jqGrid({
        url: "/URL_TO_FETCH_DATA",
        datatype: "json",
        mtype: "GET",
        colNames: ["Provider", "Title","Original Publish Time", "Fetch Time"],
        colModel:
        [
            {
                name    : "PROVIDER",
                align   : "center",
                width   : "120%",
                search  : true
            },
            {
                name    : "TITLE",
                align   : "center",
                search  : true,
                width   : "250%",
                formatter: Title_Url_Bind 
            },
            {
                name        : "PUBLISH_TIME",
                align       : "center",
                width       : "130%",
                search      : true,
                sorttype    : "datetime"

            },
            {
                name        : "DB_ENTRY_TIME",
                align       : "center",
                width       : "130%",
                sortable    : true,
                sorttype    : "datetime"
            }
        ],
        pager       : "#home_pager",
        loadonce    : true,
        shrinkToFit : true,
        rowNum      : 10,
        autoHeight  : true,
        rowList     : [10, 15, 20, 25, 50],
        sortable    : true,
        viewrecords : true,
        toolbar     : [true, "top"],
        autowidth   : true,
        beforeProcessing: beforeProcessingHandler1,
    });

    function beforeProcessingHandler1(data) {
        initializeGridFilterValueDem(data);
    }

    initializeGridFilterValueDem = function (data) {
        setSearchSelect("Provider", jQuery("#home_grid"), data);
    }

    setSearchSelect = function (columnName, grid,data) {
        grid.jqGrid('setColProp', columnName,
            {
                searchoptions: {
                    clearSearch: false,
                    sopt: ['eq', 'ne'],
                    value: buildSearchSelect(getUniqueNames(columnName, data,grid)),
                    attr: { multiple: 'multiple', size: 7},
                    dataInit: dataInitMultiselect
                }
            }
        );
    }

    buildSearchSelect = function (uniqueNames) {
        var values = "";
        $.each(uniqueNames, function () {
            values += this + ":" + this + ";";
        });
        return values.substring(0, values.length - 1);
    }

    getUniqueNames = function (columnName, mydata_parm, grid) {

        var mydata = grid.jqGrid("getGridParam", "data");

        var texts = $.map(mydata, function (item) {
            return item[columnName];
        }),

        uniqueTexts = [], textsLength = texts.length, text, textsMap = {}, 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);
            }
        }

        return uniqueTexts;
    }

    dataInitMultiselect = function (elem) {
        console.log(elem);
        setTimeout(function () {
            var $elem = $(elem), id = elem.id,
                inToolbar = typeof id === "string" && id.substr(0, 3) === "gs_",
                options = {
                    selectedList: 2,
                    height: "auto",
                    checkAllText: "all",
                    uncheckAllText: "no",
                    noneSelectedText: "Any",
                    open: function () {
                        var $menu = $(".ui-multiselect-menu:visible");
                        $menu.width("auto");
                        return;
                    }
                },
                $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';
            }
            //$elem.multiselect(options);
            $elem.multiselect(options).multiselectfilter({ placeholder: '' });
            $elem.siblings('button.ui-multiselect').css({
                width: inToolbar ? "98%" : "100%",
                marginTop: "1px",
                marginBottom: "1px",
                paddingTop: "3px"
            });
        }, 50);

    };

Большое спасибо за ответ, Да, я использую бесплатную jqGrid. Согласно упомянутому комментарию я попытался изменить код, но все еще не работал для меня. Ниже приведен обновленный код, который я пытался сделать, как указано в демонстрационной версии jqGrid MultiSelect

.

Но это выдает ошибку Uncaught ReferenceError: multiselectTemplate is not defined, Пожалуйста, дайте мне знать, как решить эту проблему. Поскольку они использовали локальные данные для загрузки jqgrid, мне трудно решить эту проблему.

    //FUNCTION TO POPULATE THE TABLE WITH THE DATA
function Grid_Table_Populator()
{
    //Populdate the Datatable with the WEB Feed data
    $("#home_grid").jqGrid({
        url: "/Web_Feed_Data",
        datatype: "json",
        mtype: "GET",
        colNames: ["ID", "PROVIDER", "Title"],
        colModel:
        [
            {
                name    : "ID",
                align   : "center",
                search  : true,
                hidden  : true
            },
            {
                name    : "PROVIDER",
                align   : "center",
                width   : "120%",
                type    : "text", 
                search  : true, 
                template: multiselectTemplate       
            },
            {
                name    : "TITLE",
                align   : "center",
                search  : true,
                width   : "250%",
                formatter: Title_Url_Bind 
            },
        ],
        pager       : "#home_pager",
        loadonce    : true,
        shrinkToFit : true,
        rowNum      : 10,
        autoHeight  : true,
        rowList     : [10, 15, 20, 25, 50],
        sortable    : true,
        sortname    : "TITLE",
        sortorder   : "desc",
        viewrecords : true,
        toolbar     : [true, "top"],
        autowidth   : true,
        caption     : 'Table Data',
        loadComplete: function(data)
        {
            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");
                });        
            }
        },
    }); 

    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");
                            var height = $menu.find(">ul>li").first().outerHeight();
                            $menu.find(">ul").css("maxHeight", 5 * Math.max(height, 12));
                            return;
                        }
                    },
                    $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);
        },    
        multiselectTemplate = {
            stype: "select", 
            searchoptions: {
                generateValue: true,
                //noFilterText: "Any",
                sopt: ["in"],
                attr: {
                    multiple: "multiple",
                    size: 3
                },
                dataInit: dataInitMultiselect
            }
    };
}

Я пытался объявить это внутри функции и за ее пределами, но все равно не повезло. Пожалуйста, помогите мне с этой проблемой.

После большой помощи от Олега я смог получить Multi-Select, но он не работал. когда я нажимаю на нее, она не раскрывается и не показывает опцию. Я разместил свой код здесь МОЙ КОД JQGRID @ Олег, пожалуйста, посмотрите на это и предоставьте мне решение.

Мой jqGrid выглядит примерно так: JQGRID COLUMMN

1 Ответ

1 голос
/ 16 июня 2019

Из других ваших вопросов видно, что вы используете бесплатный форк jqGrid. Он поддерживает генерацию уникальных значений автоматически. Таким образом, можно использовать

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 после загрузки данных с сервера. Можно проверить this.ftoolbar внутри loadComplete, например, чтобы определить, существует ли filterToolbar:

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. Функция dataInitMultiselect имеет следующую реализацию:

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/. В нем много ошибок:

  1. вы пропустили stype : "select" в столбце множественного выбора. Поле поиска должно иметь тип выбора (stype : "select"), чтобы его можно было отображать как элемент <select>, который может быть преобразован позднее с учетом управления множественным выбором
  2. Я неоднократно писал вам о важности вставки только одной версии jQuery и других библиотек JavaScript. Кроме того, важно хранить порядок вставленных файлов JS на основе зависимостей. Многоэлементный виджет является плагином для jQuery UI. Таким образом, JQuery UI должен быть вставлен раньше. Короче надо заменить
<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 входных данных определяет уникальный идентификатор каждого элемента ввода. 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. Значения width свойства colModel должны быть числами, а не строками, такими как "120%". Числа будут интерпретироваться как пиксели. Если вы используете autowidth : true, начальные значения width будут пропорционально увеличены, чтобы ширина сетки была равна ширине внешнего элемента.
  5. Наконец-то я добавил несколько CSS-правил в вашу демонстрацию
.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 в приведенном выше правиле в соответствии с вашими требованиями.

Модифицированная демоверсия https://jsfiddle.net/OlegKi/teLja6z3/25/

...