Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When using select2 (v 4.0) on a jquery UI dialog, how can I get allowClear option to work when using a remote datasource?

I am using select2 dropdown and just upgraded to version 4. The one feature that seems broken (or i am doing something wrong) is the allowClear option when you have a remote data source AND the select2 is sitting on a jquery UI dialog

It works fine if you data source is local (no ajax) or if there is no jquery UI dialog involved but when I try with a remote data source on a jquery UI dialog I see issues.

What is interesting is that when seetting allowClear = true, the "X" DOES shows up on the right side of the dropdown box after I search and choose an item, but when i click it, all of the select2 code runs but the previous selected value doesn't get removed. I have debugged the select2.js code and all of the code that seems like it should be fired (handleClear, etc) does seem to be firing properly.

When testing on a local example, I see that this line of code is what actually removes the value:

 this.$element.val(this.placeholder.id).trigger('change');

bug when I debug the same code on a remote data source, nothing seems to change at all when that line of code fires.

From googling, the only related issue I see if if you don't specify a placeholder text (example question here) but in my case, (as per below) I do specify this

Here are some screenshots:

enter image description here

enter image description here

and here is my code below that is setting up this select2 dropdown:

asp.net-MVC View:

 <% = Html.DropDownList("MyDropdownId", Model.DropdownItems, new {@id = "MyDropdown"}) %><br/><br/>

and here is my javascript:

$("#MyDropdown").select2({
    theme: "classic",
    width: "280px",
    allowClear: true,
    ajax: {
        url: "/MyController/Search",
        dataType: 'json',
        delay: 300,
        data: function (params) {
            return { q: params.term };
        },
        processResults: function (data, params) {
            return { results: data };
        },
        cache: false
    },
    escapeMarkup: function (markup) { return markup; },
    minimumInputLength: 3,
    placeholder: "Search",
    templateResult: streamFormatResult,
    templateSelection: streamSelectionResult
});

Has anyone else faced this issue or can see why clicking on the "X" in a select2 dropdown with remote data source wouldn't clear out the previously selected choice?

Update

Given Kevin's answer below, the issue seems to be isolated to the fact that my select2 dropdown is on a jquery UI dialog (as if I try it on a regular page it does work as expected)

the only other code that I had to add (to get select2 working on a jquery UI dialog) was this code:

if ($.ui && $.ui.dialog && $.ui.dialog.prototype._allowInteraction) {
    var ui_dialog_interaction = $.ui.dialog.prototype._allowInteraction;
    $.ui.dialog.prototype._allowInteraction = function (e) {
        if ($(e.target).closest('.select2-dropdown').length) return true;
        return ui_dialog_interaction.apply(this, arguments);
    };
}

Without the code above the select2 input is not editable. I am not sure if this is causing the issue to not clearing out the previous selected value when I click on the "X".

like image 712
leora Avatar asked Aug 25 '15 17:08

leora


People also ask

How do I add options in Select2?

New options can be added to a Select2 control programmatically by creating a new Javascript Option object and appending it to the control: var data = { id: 1, text: 'Barn owl' }; var newOption = new Option(data.text, data.id, false, false); $('#mySelect2').append(newOption).trigger('change');

What is the use of Select2 in jQuery?

Select2 gives you a customizable select box with support for searching, tagging, remote data sets, infinite scrolling, and many other highly used options.

How do I create a Select2 dynamically?

HTML. Create a <select class="select2_el" > element to initialize select2 on page load and create <div id="elements" > container to store <select > element on button click using jQuery AJAX.

Why Select2 is not working in modal?

Select2 does not function properly when I use it inside a Bootstrap modal. This issue occurs because Bootstrap modals tend to steal focus from other elements outside of the modal. Since by default, Select2 attaches the dropdown menu to the <body> element, it is considered "outside of the modal".


1 Answers

When using a placeholder with a single select, you must always provide an <option></option> for it, even if you are using a remote data source. This is because Select2 needs a value to set the select to (usually a blank string), and the only way it can do that is with a placeholder option.

The easy solution if you have access to the HTML is to add a blank <option> inside the <select>.

<select>
  <option></option>
</option>

You can even add some helpful text to it that will be displayed to users, the value just has to be a blank string

<select>
  <option value="">Select an option</option>
</select>

Now, some frameworks will automatically generate the <select> for you. Luckily, most of these provide a way to define the "blank" or "placeholder" option for you. And if for some reason the framework doesn't, you can usually add a new option to the list of options you are telling the framework to render.

For ASP.NET MVC, you need can control the placeholder option by passing in a another argument to Html.DropDownList.

<% = Html.DropDownList("MyDropdownId", Model.DropdownItems, "Select an option", new {@id = "MyDropdown"}) %>

And this should generate a blank placeholder at the top of the list of options.

Now, some frameworks will require that the placeholder option has a value other than a blank string. Select2 supports setting a custom placeholder value by passing in a data object instead of a string for the placeholder.

So for HTML that looks like

<select>
  <option value="-1">Select an option</option>
</select>

You would initialize Select2 using the following code for the placeholder

$('select').select2({
  placeholder: {
    id: '-1',
    text: 'Custom placeholder text'
  }
});

Here's an example of a remote data source (mocked, in this case) working with placeholder and allowClear. Keep in mind that you won't need to set ajax.transport, that's only needed because we aren't actually making a remote request.

$('.js-states').select2({
  placeholder: {
    id: "-1",
    text: "Select a state..."
  },
  allowClear: true,
  ajax: {
    url: "/MyController/Search",
    dataType: 'json',
    delay: 300,
    data: function (params) {
      return { q: params.term };
    },
    processResults: function (data, params) {
      return { results: data };
    },
    cache: false,
    transport: function (params, success, failure) {
      var term = params.data.q || "";
      
      // mock response
      var response = [
        {
          id: "AK",
          text: "Alaska"
        },
        {
          id: "AL",
          text: "Alabama"
        },
        {
          id: "AZ",
          text: "Arizona"
        },
        {
          id: term || "nothing",
          text: term || ""
        }
      ];
      
      success(response);
    }
  }
});
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>

<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js"></script>

<select class="js-states" style="width: 50%">
  <option value="-1">Select a state</option>
</select>
like image 77
Kevin Brown-Silva Avatar answered Oct 25 '22 05:10

Kevin Brown-Silva