2

I wanted to destroy and recreate multiselect widget from Telerik's Kendo UI. Normally it is easy thing which I done much times before, but never with multiselect. The problem I am facing now is that way which should work (atleast I think it should) ... does not.

Here is code which I am using to destroy and recreate components like grids or dropdowns:

if ($('#dropdown1').data('kendoDropDownList')) {
    $('#dropdown1').data('kendoDropDownList').destroy();
    $('#dropdown1').html('');
}

How i said - If I use it on dropdown or grid - it works. But on the multiselect it does not:

if ($('#multiselect1').data('kendoMultiSelect')) {
    $('#multiselect1').data('kendoMultiSelect').destroy();
    $('#multiselect1').html('');
}

I prepared small Dojo example where is shown the behaviour. When dropdown is destroyed and recreated it looks correct. When I do the same to Multiselect it always add widget as next line.

Of course I can overcome this problem by changing dataSource and just call read method or something like that but I whould like to know if it is bug or there is another way how to destroy multiselects.

Thanks.

Ademar
  • 1,418
  • 1
  • 17
  • 27

3 Answers3

9

This code uses unwrap() to remove the original input from the kendo wrapper div and then .remove() to get rid of leftover kendo DOM elements:

$('html').on('click', '#destroy2', function(e){
  if ($('#multiselect1').data('kendoMultiSelect')) {
    alert('multiselect exists - destroying and recreating');

    $('#multiselect1').data('kendoMultiSelect').destroy();
    $('#multiselect1').unwrap('.k-multiselect').show().empty();
    $(".k-multiselect-wrap").remove();

    $("#multiselect1").kendoMultiSelect({
      dataSource: {
        data: ["Three3", "Four4"]
      }
    });

    $('#text2').text('Multiselect AFTER calling destroy');
  }

});

ezanker
  • 24,628
  • 1
  • 20
  • 35
  • Thank you, this solution looks the most convenient to me. – Ademar Oct 19 '16 at 13:06
  • @Ademar, you are welcome. This does seem like a bug in KendoUI. I would expect destroy() to get you back to the original markup... – ezanker Oct 19 '16 at 13:07
  • .destroy() does not get rid of the wrapper elements for any widget(even the DropDownList in this example). It is just that MultiSelect does not seem to handle the wrapper already being there as well as the other widgets. .destroy() *does* remove the "detached" mark-up(popups, etc)...except for ContextMenu for some reason. – The Dread Pirate Stephen Oct 19 '16 at 17:42
1

When you clear the html of multiselect1, it still leaves behind all the other dom elements created when the input is turned into a widget. Then when you recreate it, it doesn't quite handle it as well as the dropdownlist, which I think could be a bug.

If you instead wrap the controls you need to recreate in a div element and clear that element instead, it will get rid of all the extra elements so that you can start will a clean slate to create the new one.

http://dojo.telerik.com/@Stephen/EDaYA

<div id='multiselectDiv'>
    <input id="multiselect1" />
</div>

$('html').on('click', '#destroy2', function(e){
  if ($('#multiselect1').data('kendoMultiSelect')) {
      alert('multiselect exists - destroying and recreating');

      $('#multiselect1').data('kendoMultiSelect').destroy();
      $('#multiselectDiv').empty();

      $('#multiselectDiv').append('<input id="multiselect1" />')
      $("#multiselect1").kendoMultiSelect({
      dataSource: {
         data: ["Three3", "Four4"]
      }
});
The Dread Pirate Stephen
  • 3,089
  • 1
  • 12
  • 14
  • Thank you, it works but solution from @ezanker it more suitable for me because I do not want create wrapper div if it is not necessary.. – Ademar Oct 19 '16 at 13:07
0

I updated you code to this and it works:

$('html').on('click', '#destroy2', function(e){
  if ($('#multiselect1').data('kendoMultiSelect')) {
    alert('multiselect exists - destroying and recreating');
    var multiSelect = $('#multiselect1').data("kendoMultiSelect");
        multiSelect.value([]);
    $("#multiselect1").remove();
    $("#multiselect1").kendoMultiSelect({
      dataSource: {
        data: ["Three3", "Four4"]
      }
});

    $('#text2').text('Multiselect AFTER calling destroy');
  }
}); 

Use remove will work once

Neo
  • 3,309
  • 7
  • 35
  • 44
  • You should double-check your answer... it doesn't work – Dekel Oct 19 '16 at 12:34
  • Hello @MisterPositive, thank you for answer. Can you please update it directly into dojo example? Because when I use your code it just crash because of _ $('#multiselect1').kendoMultiSelect.destroy();_ line as you can see [here](http://dojo.telerik.com/AdOFO/9). Maybe I am missing something but I can't get it works. Thank you. – Ademar Oct 19 '16 at 12:50
  • Well, in your provided example it crashes on same line. If you check console error log you will see Uncaght TypeError. Also, if you check items in the multiselect there are still old options. – Ademar Oct 19 '16 at 12:52