This is a migrated thread and some comments may be shown as answers.

Sortable MultiSelect

3 Answers 351 Views
MultiSelect
This is a migrated thread and some comments may be shown as answers.
Dave
Top achievements
Rank 1
Dave asked on 15 May 2015, 10:50 AM

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

 

3 Answers, 1 is accepted

Sort by
0
Dave
Top achievements
Rank 1
answered on 15 May 2015, 11:31 AM

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);
            });
        }
    });
}

0
Georgi Krustev
Telerik team
answered on 19 May 2015, 08:10 AM
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!
 
0
Dave
Top achievements
Rank 1
answered on 19 May 2015, 09:33 AM

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);
    }
});

Tags
MultiSelect
Asked by
Dave
Top achievements
Rank 1
Answers by
Dave
Top achievements
Rank 1
Georgi Krustev
Telerik team
Share this question
or