使用查询字符串参数

时间:2018-04-03 17:23:46

标签: kendo-grid

我正在实现一个自定义解决方案,它将使用查询字符串参数将过滤器应用于网格来初始化kendoGrid(及其多选列)。我正在使用Kendo UI v2014.2.903和multiselectbox用户扩展。

为了实现这一点,我有一个custom JavaScript function,它将查询字符串参数解析为filter对象,并使用其filter方法将其应用于kendoGrid的dataSource属性。以下代码段:

    var preFilterQueryString = getPreFilterQuery(queryString);
    if (preFilterQueryString != '') {                     
        kendoGrid.dataSource.filter(parseFilterString(preFilterQueryString));
    }

我正在按如下方式初始化multiselectbox:

    args.element.kendoMultiSelectBox({
           dataSource: getAutoCompleteDataSource(column.field),
           valuePrimitive: true,
           selectionChanged: function (e) {
           //ignored for brevity
           }
    });

我的问题是如果我使用上述方法将过滤器设置为multiselectbox,它们不会正确应用于数据集。

例如,如果我将单个过滤器作为" Vancouver",则会显示正确的结果集。多选框中的选择是"全部"和#34;温哥华"。但是,在多选框中不检查温哥华的选择。这是设计的吗?请看下面的图片。

single filter image

如果我通过两个过滤器温哥华和华沙,只有最后一个过滤器华沙应用于网格,并且显示仅包含华沙的数据集。同样,在multiselectbox中没有选中任何选项。

two filters image

以下是应用于dataSource.filter()方法的过滤器对象。

kendoGrid's filter object image

疑难解答

以下是multiselectbox列的selectionchanged事件处理程序的压缩版本(为简洁起见)。

    if (e.newValue && e.newValue.length) {
        var newValue = e.newValue;                                   
        console.log('e.newValue: ' + e.newValue);
        filter.filters = [];
        for (var i = 0, l = newValue.length; i < l; i++) {                                                                                                   
              filter.filters.push({field: field,operator: 'contains',value: newValue[i]});
          }
        kendoGrid.dataSource.filter(allFilters);
      }

我注意到,当两个过滤器通过时,e.newValue是&#34;华沙&#34;而不是阵列 - &#34; [温哥华,华沙]&#34;

我花了很多时间来解决为什么只有华沙应用于数据集。 这是我发现的:

_raiseSelectionChanged函数是引发选择更改事件的内容。在该函数中,我注意到它设置了newValue和oldValue事件参数。要设置newValue,它使用&#34; Value&#34;功能。值函数使用以下代码检索所有选定的列表项并返回它们。

   else {
            var selecteditems = this._getSelectedListItems();
            return $.map(selecteditems, function (item) {
                var obj = $(item).children("span").first();
                return obj.attr("data-value");
            }).join();
        }

_getSelectedListItems函数使用jQuery过滤器来获取所有具有css类的列表项&#34; .selected&#34;

    _getSelectedListItems: function () {
        return this._getAllValueListItems().filter("." + SELECTED);
    },

有一个_select事件似乎正在添加&#34;。选择&#34;用于列出项目的类。当我在第286行放置一个断点时,它只打了一次,这就是华沙。我无法理解为什么它不会被称为温哥华。我没有线索,想知道是否有人有指针。

debug capture of _select function

以下是kendoMultiSelectBox用户扩展供您参考:

    //MultiSelect - A user extension of KendoUI DropDownList widget.           
    (function ($) {

// shorten references to variables
var kendo = window.kendo,
    ui = kendo.ui,
    DropDownList = ui.DropDownList,
    keys = kendo.keys,
    SELECT = "select",
    SELECTIONCHANGED = "selectionChanged",
    SELECTED = "k-state-selected",
    HIGHLIGHTED = "k-state-active",
    CHECKBOX = "custom-multiselect-check-item",
    SELECTALLITEM = "custom-multiselect-selectAll-item",
    MULTISELECTPOPUP = "custom-multiselect-popup",
    EMPTYSELECTION = "custom-multiselect-summary-empty";



var lineTemplate = '<input type="checkbox" name="#= {1} #" value="#= {0} #" class="' + CHECKBOX + '" />' +
                   '<span data-value="#= {0} #">#= {1} #</span>';



var MultiSelectBox = DropDownList.extend({

    init: function (element, options) {
        options.template = kendo.template(kendo.format(lineTemplate, options.dataValueField || 'data', options.dataTextField || 'data'));

        // base call to widget initialization
        DropDownList.fn.init.call(this, element, options);

        var button = $('<input type="button" value="OK" style="float: right; padding: 3px; margin: 5px; cursor: pointer;" />');
        button.on('click', $.proxy(this.close, this));

        var popup = $(this.popup.element);
        popup.append(button);

    },

    options: {
        name: "MultiSelectBox",
        index: -1,
        showSelectAll: true,
        preSummaryCount: 1,  // number of items to show before summarising
        emptySelectionLabel: '',  // what to show when no items are selected
        selectionChanged: null // provide callback to invoke when selection has changed
    },

    events: [
        SELECTIONCHANGED
    ],

    refresh: function () {
        // base call
        DropDownList.fn.refresh.call(this);

        this._updateSummary();

        $(this.popup.element).addClass(MULTISELECTPOPUP);
    },


    current: function (candidate) {
        return this._current;
    },


    open: function () {
        var self = this;

        this._removeSelectAllItem();

        this._addSelectAllItem();

        if ($(this.ul).find('li').length > 6) {
            $(this.popup.element).css({ 'padding-bottom': '30px' });
        }
        else {
            $(this.popup.element).css({ 'padding-bottom': '0' });
        }

        DropDownList.fn.open.call(this);

        //hook on to popup event because dropdown close does not
        //fire consistently when user clicks on some other elements
        //like a dataviz chart graphic
        this.popup.one('close', $.proxy(this._onPopupClosed, this));
    },

    _onPopupClosed: function () {

        this._removeSelectAllItem();

        this._current = null;

        this._raiseSelectionChanged();
    },

    _raiseSelectionChanged: function () {
        var currentValue = this.value();
        var currentValues = $.map((currentValue.length > 0 ? currentValue.split(",") : []).sort(), function (item) { return item.toString(); });
        var oldValues = $.map((this._oldValue || []).sort(), function (item) { return item ? item.toString() : ''; });

        // store for next pass
        this._oldValue = $.map(currentValues, function (item) { return item.toString(); });

        var changedArgs = { newValue: currentValues, oldValue: oldValues };

        if (oldValues) {

            var hasChanged = ($(oldValues).not(currentValues).length == 0 && $(currentValues).not(oldValues).length == 0) !== true;

            if (hasChanged) {
                //if (this.options.selectionChanged)
                //    this.options.selectionChanged(changedArgs);
                this.trigger(SELECTIONCHANGED, changedArgs);
            }
        }
        else if (currentValue.length > 0) {
            //if (this.options.selectionChanged)
            //    this.options.selectionChanged(changedArgs);
            this.trigger(SELECTIONCHANGED, changedArgs);
        }
    },

    _addSelectAllItem: function () {

        if (!this.options.showSelectAll) return;

        var firstListItem = this.ul.children('li:first');

        if (firstListItem.length > 0) {
            this.selectAllListItem = $('<li tabindex="-1" role="option" unselectable="on" class="k-item ' + SELECTALLITEM + '"></li>').insertBefore(firstListItem);

            // fake a data object to use for the template binding below
            var selectAllData = {};
            selectAllData[this.options.dataValueField || 'data'] = '*';
            selectAllData[this.options.dataTextField || 'data'] = 'All';

            this.selectAllListItem.html(this.options.template(selectAllData));

            this._updateSelectAllItem();

            this._makeUnselectable(); // required for IE8
        }
    },


    _removeSelectAllItem: function () {

        if (this.selectAllListItem) {
            this.selectAllListItem.remove();
        }
        this.selectAllListItem = null;
    },


    _focus: function (li) {
        if (this.popup.visible() && li && this.trigger(SELECT, { item: li })) {
            this.close();
            return;
        }
        this.select(li);
    },

    _keydown: function (e) {

        // currently ignore Home and End keys
        // can be added later
        if (e.keyCode == kendo.keys.HOME ||
            e.keyCode == kendo.keys.END) {
            e.preventDefault();
            return;
        }

        DropDownList.fn._keydown.call(this, e);
    },

    _keypress: function (e) {
        // disable existing function
    },

    _move: function (e) {
        var that = this,
            key = e.keyCode,
            ul = that.ul[0],
            down = key === keys.DOWN,
            pressed;

        if (key === keys.UP || down) {

            if (down) {

                if (!that.popup.visible()) {
                    that.toggle(down);
                }
                if (!that._current) {
                    that._current = ul.firstChild;
                } else {
                    that._current = ($(that._current)[0].nextSibling || that._current);
                }

            } else {
                //up

                // only if anything is highlighted
                if (that._current) {
                    that._current = ($(that._current)[0].previousSibling || ul.firstChild);
                }
            }


            if (that._current) {
                that._scroll(that._current);
            }

            that._highlightCurrent();

            e.preventDefault();
            pressed = true;

        } else {
            pressed = DropDownList.fn._move.call(this, e);
        }

        return pressed;
    },


    selectAll: function () {

        var unselectedItems = this._getUnselectedListItems();
        this._selectItems(unselectedItems);

        // todo: raise custom event
    },

    unselectAll: function () {

        var selectedItems = this._getSelectedListItems();
        this._selectItems(selectedItems);  // will invert the selection

        // todo: raise custom event
    },


    _selectItems: function (listItems) {
        var that = this;

        $.each(listItems, function (i, item) {
            var idx = ui.List.inArray(item, that.ul[0]);
            that.select(idx);  // select OR unselect
        });
    },

    _selectItem: function () {
        // method override to prevent default selection of first item, done by normal dropdown
        var that = this,
            options = that.options,
            useOptionIndex,
            value;

        useOptionIndex = that._isSelect && !that._initial && !options.value && options.index && !that._bound;

        if (!useOptionIndex) {
            value = that._selectedValue || options.value || that._accessor();
        }

        if (value) {
            that.value(value);
        } else if (that._bound === undefined) {
            that.select(options.index);
        }
    },

    _select: function (li) {
        var that = this,
             value,
             text,
             idx;

        li = that._get(li);

        if (li && li[0]) {
            idx = ui.List.inArray(li[0], that.ul[0]);
            if (idx > -1) {

                if (li.hasClass(SELECTED)) {
                    li.removeClass(SELECTED);
                    that._uncheckItem(li);

                    if (this.selectAllListItem && li[0] === this.selectAllListItem[0]) {
                        this.unselectAll();
                    }
                } else {
                    li.addClass(SELECTED);
                    that._checkItem(li);

                    if (this.selectAllListItem && li[0] === this.selectAllListItem[0]) {
                        this.selectAll();
                    }
                }

                if (this._open) {
                    that._current(li);
                    that._highlightCurrent();
                }

                var selecteditems = this._getSelectedListItems();
                value = [];
                text = [];
                $.each(selecteditems, function (indx, item) {
                    var obj = $(item).children("span").first();
                    value.push(obj.attr("data-value"));
                    text.push(obj.text());
                });

                that._updateSummary(text);

                that._updateSelectAllItem();

                that._accessor(value, idx);

                // todo: raise change event (add support for selectedIndex) if required
                that._raiseSelectionChanged();
            }
        }

    },

    _getAllValueListItems: function () {
        if (this.selectAllListItem) {
            return this.ul.children("li").not(this.selectAllListItem[0]);
        } else {
            return this.ul.children("li");
        }
    },

    _getSelectedListItems: function () {
        return this._getAllValueListItems().filter("." + SELECTED);
    },

    _getUnselectedListItems: function () {
        return this._getAllValueListItems().filter(":not(." + SELECTED + ")");
    },

    _getSelectedItemsText: function () {

        var text = [];
        var selecteditems = this._getSelectedListItems();
        $.each(selecteditems, function (indx, item) {
            var obj = $(item).children("span").first();
            text.push(obj.text());
        });
        return text;
    },

    _updateSelectAllItem: function () {
        if (!this.selectAllListItem) return;

        // are all items selected?
        if (this._getAllValueListItems().length == this._getSelectedListItems().length) {
            this._checkItem(this.selectAllListItem);
            this.selectAllListItem.addClass(SELECTED);
        }
        else {
            this._uncheckItem(this.selectAllListItem);
            this.selectAllListItem.removeClass(SELECTED);
        }
    },

    _updateSummary: function (itemsText) {

        if (!itemsText) {
            itemsText = this._getSelectedItemsText();
        }

        if (itemsText.length == 0) {
            this._inputWrapper.addClass(EMPTYSELECTION);
            this.text(this.options.emptySelectionLabel);
            return;
        } else {
            this._inputWrapper.removeClass(EMPTYSELECTION);
        }

        if (itemsText.length <= this.options.preSummaryCount) {
            this._textAccessor(itemsText.join(", "));
        }
        else {
            this._textAccessor(itemsText.length + ' selected');
        }
    },

    _checkItem: function (itemContainer) {
        if (!itemContainer) return;
        itemContainer.children("input").prop("checked", true);
    },

    _uncheckItem: function (itemContainer) {
        if (!itemContainer) return;
        itemContainer.children("input").removeAttr("checked");
    },

    _isItemChecked: function (itemContainer) {
        return itemContainer.children("input:checked").length > 0;
    },

    value: function (value) {
        if(value != undefined)
            console.log("value", value);
        var that = this,
            idx,
            valuesList = [];

        if (value !== undefined) {

            if (!$.isArray(value)) {
                valuesList.push(value);
                this._oldValue = valuesList; // to allow for selectionChanged event
            }
            else {
                valuesList = value;
                this._oldValue = value; // to allow for selectionChanged event
            }

            // clear all selections first
            $(that.ul[0]).children("li").removeClass(SELECTED);
            $("input", that.ul[0]).removeAttr("checked");

            $.each(valuesList, function (indx, item) {

                var hasValue;

                if (item !== null) {
                    item = item.toString();
                }

                that._selectedValue = item;

                hasValue = value || (that.options.optionLabel && !that.element[0].disabled && value === "");
                if (hasValue && that._fetchItems(value)) {
                    return;
                }

                idx = that._index(item);

                if (idx > -1) {
                    that.select(
                        that.options.showSelectAll ? idx + 1 : idx
                    );
                }
            });

            that._updateSummary();
        }
        else {
            var selecteditems = this._getSelectedListItems();
            return $.map(selecteditems, function (item) {
                var obj = $(item).children("span").first();
                return obj.attr("data-value");
            }).join();
        }
    },

});

ui.plugin(MultiSelectBox);

   })(jQuery);

更新

我遇到了multiselectbox的select事件的文档,该事件明确指出在以编程方式选择项目时不会触发select事件。它与我想要做的有关吗?但是,即使我以编程方式设置它们,为什么还要为其中一个过滤器触发?

enter link description here

0 个答案:

没有答案