Dynamically add item to jQuery Select2 control that uses AJAX
Asked Answered
B

9

63

I have a jQuery Select2 control that uses AJAX to populate:

<input type="text" name="select2" id="select2" style='width:400px' value="999">

var initialSelection = { id: '999', text:"Some initial option"};

$("#select2").select2({
    placeholder: "Select Option",
    minimumInputLength: 2,
    ajax: { 
        url: "/servletToGetMyData",
        dataType: 'json',
        data: function (term, page) { return { term: term }; },
        results: function (data, page) {  return { results: data.results} }
    },
    initSelection : function(element, callback){ callback(initialSelection); },     
    escapeMarkup: function (m) { return m; }
}); 

The AJAX links to a database of possible options and as you can see requires two characters of input.

The problem is the user can use a dialog to add a new option if the option doesn't exist in the database. Upon return from that dialog, I try:

var o = $("<option/>", {value: newID, text: newText});
$('#select2').append(o);
$('#select2 option[value="' + newID + '"]').prop('selected',true);
$('#select2').trigger('change');

But it doesn't work. The same exact code works for non-AJAX Select2 boxes. I've tried various alternatives, like using $('#select2').select2("val", newID); but it doesn't work.

I've even tried completely deleting the Select2 control. However, $('#select2').remove() only removes the original <input> field but leaves the Select2 control lingering around. Note that the page has more than one Select2 control, so I can't use a class selector for Select2 controls as it will remove other controls that I need.

Any idea how to either a) dynamically add an option to a Select2 control that uses AJAX; or b) completely delete a Select2 control so that it can be programmatically added back? Or any other solution...

Edit I found another question that shows how to remove a select2 element, using .select2("destroy"). This works but is, in my opinion, sub-optimal. I would much prefer to be able to just add the option than to destroy and re-create the select2.

Bandeau answered 21/8, 2014 at 14:1 Comment(1)
Is it bad to mention the version of plugin?Funda
B
39

This provided a simple solution: Set data in Select2 after insert with AJAX

$("#select2").select2('data', {id: newID, text: newText});      
Bandeau answered 21/8, 2014 at 16:43 Comment(3)
this solution do not work for the select multiple, just add selected items, but not in the options list.Caliban
it is not working in multiple select dropdown, it is neither appearing as seleted nor it is appearing in option list.Darrin
This works for older versions of Select2. For version 4, see the answer by alexw.Bandeau
M
59

This is a lot easier to do starting in select2 v4. You can create a new Option, and append it to the select element directly. See my codepen or the example below:

$(document).ready(function() {
    $("#state").select2({
      tags: true
    });
      
    $("#btn-add-state").on("click", function(){
      var newStateVal = $("#new-state").val();
      // Set the value, creating a new option if necessary
      if ($("#state").find("option[value=" + newStateVal + "]").length) {
        $("#state").val(newStateVal).trigger("change");
      } else { 
        // Create the DOM option that is pre-selected by default
        var newState = new Option(newStateVal, newStateVal, true, true);
        // Append it to the select
        $("#state").append(newState).trigger('change');
      } 
    });  
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/css/select2.min.css" rel="stylesheet"/>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.min.js"></script>


<select id="state" class="js-example-basic-single" type="text" style="width:90%">
  <option value="AL">Alabama</option>
  <option value="WY">Wyoming</option>
</select>
<br>
<br>
<input id="new-state" type="text" />
<button type="button" id="btn-add-state">Set state value</button>

Hint: try entering existing values into the text box, like "AL" or "WY". Then try adding some new values.

Motivity answered 13/2, 2016 at 22:20 Comment(6)
it works but problem is when I change option, newly added option goneSteeple
This is the way to go. TLDR: $("#my_select").append(new Option("Label", "value", true, true));Biogenesis
@Motivity append This method work perfectly fine for single selectbox, but not for multiselect. Can you please suggest.Chesterchesterfield
İt works but how do we add additional data into select option ?Midyear
@alexw. Is it possible to pass extra HTML code in this way ?Parcel
This does not work for me... select2 rejects if I try to use a <select> tag with ajax. I have to use <input> tag, and attaching <option> to <input> does not work.Odaodab
B
39

This provided a simple solution: Set data in Select2 after insert with AJAX

$("#select2").select2('data', {id: newID, text: newText});      
Bandeau answered 21/8, 2014 at 16:43 Comment(3)
this solution do not work for the select multiple, just add selected items, but not in the options list.Caliban
it is not working in multiple select dropdown, it is neither appearing as seleted nor it is appearing in option list.Darrin
This works for older versions of Select2. For version 4, see the answer by alexw.Bandeau
W
29

In case of Select2 Version 4+

it has changed syntax and you need to write like this:

// clear all option
$('#select_with_blank_data').html('').select2({data: [{id: '', text: ''}]});

// clear and add new option
$("#select_with_data").html('').select2({data: [
 {id: '', text: ''},
 {id: '1', text: 'Facebook'},
 {id: '2', text: 'Youtube'},
 {id: '3', text: 'Instagram'},
 {id: '4', text: 'Pinterest'}]});



//  append option
$("#select_with_data").append('<option value="5">Twitter</option>');
$("#select_with_data").val('5');
$("#select_with_data").trigger('change');
Wrapped answered 10/5, 2015 at 9:29 Comment(1)
This is "documented" as no longer possible in select2 code. You'll get a warning if you set 'debug:true' in the select2 constructor: "Select2: Data can no longer be set using select2("data"). You should consider setting the value instead using $element.val()."Galan
N
23

In Select2 4.0.2

$("#yourId").append("<option value='"+item+"' selected>"+item+"</option>");
$('#yourId').trigger('change'); 
Nahshunn answered 28/6, 2016 at 19:25 Comment(2)
Sometimes I wish I had more time to develop an alternative to select2.... I can't believe that this worked for multiple options and what I have to do for single options is totally different...thanks @NahshunnKashmir
fyi, still working in 4.0.6 tested and needed today... THXContrapuntal
Q
10

I have resolved issue with the help of this link http://www.bootply.com/122726. hopefully will help you

Add option in select2 jquery and bind your ajax call with created link id(#addNew) for new option from backend. and the code

 $.getScript('http://ivaynberg.github.io/select2/select2-3.4.5/select2.js',function(){

  $("#mySel").select2({
    width:'240px',
    allowClear:true,
    formatNoMatches: function(term) {
        /* customize the no matches output */
        return "<input class='form-control' id='newTerm' value='"+term+"'><a href='#' id='addNew' class='btn btn-default'>Create</a>"
    }
  })
  .parent().find('.select2-with-searchbox').on('click','#addNew',function(){
    /* add the new term */
    var newTerm = $('#newTerm').val();
    //alert('adding:'+newTerm);
    $('<option>'+newTerm+'</option>').appendTo('#mySel');
    $('#mySel').select2('val',newTerm); // select the new term
    $("#mySel").select2('close');       // close the dropdown
  })

});



<div class="container">
    <h3>Select2 - Add new term when no search matches</h3>
    <select id="mySel">
        <option>One</option>
        <option>Two</option>
        <option>Three</option>
        <option>Four</option>
        <option>Five</option>
        <option>Six</option>
        <option>Twenty Four</option>
    </select>
    <br>
    <br>
</div>
Quarto answered 3/12, 2014 at 13:21 Comment(4)
Please share at least a summary of what you found behind the link. This in case the link stops working in the future.Towland
select2 javascript modification and going to update the answerQuarto
any chance to upgrade the current code for select 2 version 4.0. Current sample code is break. ThanksMariannamarianne
@Quarto The solution provided you is creating issue , after adding in dropdown prntscr.com/a1r0b1Petronius
A
9

Extending on Bumptious Q Bangwhistle's answer:

$('#select2').append($('<option>', { 
    value: item,
    text : item 
})).select2();

This would add the new options into the <select> tags and lets select2 re-render it.

Abnormity answered 25/6, 2016 at 11:15 Comment(0)
G
5

I did it this way and it worked for me like a charm.

var data = [{ id: 0, text: 'enhancement' }, { id: 1, text: 'bug' }, { id: 2, 

    text: 'duplicate' }, { id: 3, text: 'invalid' }, { id: 4, text: 'wontfix' }];

    $(".js-example-data-array").select2({
      data: data
    })
Gleeful answered 9/4, 2017 at 13:19 Comment(0)
C
4
$("#my_select").select2('destroy').empty().select2({data: [{id: 1, text: "new_item"}]});
Clamshell answered 14/7, 2016 at 13:48 Comment(1)
Please provide some more information to your answer. An explanation could help.Gearhart
S
2

To get dynamic tagging to work with ajax, here's what I did.

Select2 version 3.5

This is easy in version 3.5 because it offers the createSearchChoice hook. It even works for multiple select, as long as multiple: true and tags: true are set.

HTML

<input type="hidden" name="locations" value="Whistler, BC" />

JS

$('input[name="locations"]').select2({
  tags: true,
  multiple: true,
  createSearchChoice: function(term, data) {
    if (!data.length)
      return { id: term, text: term };
    },
  ajax: {
    url: '/api/v1.1/locations',
    dataType: 'json'
  }
});

The idea here is to use select2's createSearchChoice hook which passes you both the term that the user entered and the ajax response (as data). If ajax returns an empty list, then tell select2 to offer the user-entered term as an option.

Demo: https://johnny.netlify.com/select2-examples/version3


Select2 version 4.X

Version 4.X doesn't have a createSearchChoice hook anymore, but here's how I did the same thing.

HTML

  <select name="locations" multiple>
    <option value="Whistler, BC" selected>Whistler, BC</option>
  </select>

JS

$('select[name="locations"]').select2({
  ajax: {
    url: '/api/v1.1/locations',
    dataType: 'json',
    data: function(params) {
      this.data('term', params.term);
      return params;
    },
    processResults: function(data) {
      if (data.length)
        return {
          results: data
        };
      else
        return {
          results: [{ id: this.$element.data('term'), text: this.$element.data('term') }]
        };
    }
  }
});

The ideas is to stash the term that the user typed into jQuery's data store inside select2's data hook. Then in select2's processResults hook, I check if the ajax response is empty. If it is, I grab the stashed term that the user typed and return it as an option to select2.

Demo: https://johnny.netlify.com/select2-examples/version4

Smokedry answered 19/3, 2019 at 18:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.