Sortable MultiSelect

4 posts, 0 answers
  1. Dave
    Dave avatar
    4 posts
    Member since:
    May 2015

    Posted 15 May 2015 Link to this post

    I have a MultiSelect which is also sortable (so the selected items can be reordered): 

    el.kendoMultiSelect({
        dataSource: settings.dataSource,
        dataTextField: settings.dataTextField,
        dataValueField: settings.dataValueField,
        autoClose: false,
        animation: false
    });
     
    var multiSelectData = el.data("kendoMultiSelect");
     
    multiSelectData.tagList.kendoSortable({
        hint: function (element) {
            return element.clone().addClass("hint");
        },
        placeholder: function (element) {
            return element.clone().addClass("placeholder").text(settings.dropText);
        },
    });

    When I get the values -  multiSelectData.value() - they're in order which they were added, instead of the order that they've been arranged in to.

    Is there a way I can have the MultiSelect update the values when an item is reordered, without delving into the 'private' properties of the MultiSelect?

     

    Thanks in advance,
    Dave

     

  2. Dave
    Dave avatar
    4 posts
    Member since:
    May 2015

    Posted 15 May 2015 in reply to Dave Link to this post

    Interested in hearing a cleaner solution. Here's one which works, but only by messing around with the private properties.

    Sample Usage:

    var itemSelector = new Telerik.Extensions.SortableMultiSelect({
        el: $('#divSelectItems')
    });

     

    Here's the code. 

    var Telerik = Telerik || {};
    Telerik.Extensions = Telerik.Extensions || {};

    Telerik.Extensions.SortableMultiSelect = function (config) {
        this.defaults = {
            el: null, // $('#el')
            dataTextField: "label",
            dataValueField: "value",
            dataSource: null,
            dropText: 'drop here'
        };
     
        var _this = this;
        var settings = $.extend(this.defaults, config);
     
        if (!settings.el) {
            throw Error("SortableMultiSelect: No element specified");
        }
     
        settings.el.kendoMultiSelect({
            dataSource: settings.dataSource,
            dataTextField: settings.dataTextField,
            dataValueField: settings.dataValueField,
            autoClose: false,
            animation: false
        });
     
        this.multiSelect = settings.el.data("kendoMultiSelect");
     
        this.multiSelect.tagList.kendoSortable({
            hint: function (element) {
                return element.clone().addClass("hint");
            },
            placeholder: function (element) {
                return element.clone().addClass("placeholder").text(settings.dropText);
            },
            end: function (evt) {
                var dI = _this.multiSelect.dataItems();
                var adjustedOldIndex = evt.newIndex - evt.oldIndex > 0 ? evt.oldIndex : evt.oldIndex + 1;
                var adjustedNewIndex = evt.newIndex - evt.oldIndex > 0 ? evt.newIndex +1 : evt.newIndex;
                dI.splice(adjustedNewIndex, 0, dI[evt.oldIndex]);
                dI.splice(adjustedOldIndex, 1);
                _this.multiSelect.listView._dataItems = dI;
                _this.multiSelect.listView._values = [];
                $.each(dI, function (idx, item) {
                    _this.multiSelect.listView._values.push(item.value);
                });
            }
        });
    }

  3. Kendo UI is VS 2017 Ready
  4. Georgi Krustev
    Admin
    Georgi Krustev avatar
    3707 posts

    Posted 19 May 2015 Link to this post

    Hello Dave,

    Indeed, the tag res-positioning will not update the order of the selected values. The only feasible way is to update the selected values order manually. The available approaches that I can think of are:

    - Modify the internal fields, but this is error prone as those fields can change in future.
    - Re-set the value. In this case, the values positions are updated and then re-set back to the widget using the value method.

    In both cases, you will need to update the selected values order manually.

    Regards,
    Georgi Krustev
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  5. Dave
    Dave avatar
    4 posts
    Member since:
    May 2015

    Posted 19 May 2015 in reply to Georgi Krustev Link to this post

    Thanks Georgi. I've found an alternative solution.

    On the change event for the sortable, loop through the selected items. This returns the elements in the right order. I can then $.grep to get the correct item from the datsource (based on the 'label' property), add the items value property to an array, and then set the value of the multiselect to that array.

    Seems to work a treat - code attached.

    Cheers,
    Dave.

     

    multiSelect.tagList.kendoSortable({
        hint: function (element) {
            return element.clone().addClass("hint");
        },
        placeholder: function (element) {
            return element.clone().addClass("placeholder").text(settings.dropText);
        },
        change: function(evt) {
            var multiSelectItems = multiSelect.dataSource.data();
            var sortedValues = [];
            $.each(this.items(), function(idx,item) {
                var i = $.grep(multiSelectItems, function (gItm, gIdx) {
                    return gItm.label == $(item).children('span:first').html(); // Gets the 'label' for the item
                })[0]; // there will only ever be one
                sortedValues.push(i.value); // value property
            });
            multiSelect.value(sortedValues);
        }
    });

Back to Top
Kendo UI is VS 2017 Ready