[jquery] Dynamically add item to jQuery Select2 control that uses AJAX

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.

This question is related to jquery ajax jquery-select2

The answer is


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


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>

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

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

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:

_x000D_
_x000D_
$(document).ready(function() {_x000D_
    $("#state").select2({_x000D_
      tags: true_x000D_
    });_x000D_
      _x000D_
    $("#btn-add-state").on("click", function(){_x000D_
      var newStateVal = $("#new-state").val();_x000D_
      // Set the value, creating a new option if necessary_x000D_
      if ($("#state").find("option[value=" + newStateVal + "]").length) {_x000D_
        $("#state").val(newStateVal).trigger("change");_x000D_
      } else { _x000D_
        // Create the DOM option that is pre-selected by default_x000D_
        var newState = new Option(newStateVal, newStateVal, true, true);_x000D_
        // Append it to the select_x000D_
        $("#state").append(newState).trigger('change');_x000D_
      } _x000D_
    });  _x000D_
});
_x000D_
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>_x000D_
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/css/select2.min.css" rel="stylesheet"/>_x000D_
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>_x000D_
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.1/js/select2.min.js"></script>_x000D_
_x000D_
_x000D_
<select id="state" class="js-example-basic-single" type="text" style="width:90%">_x000D_
  <option value="AL">Alabama</option>_x000D_
  <option value="WY">Wyoming</option>_x000D_
</select>_x000D_
<br>_x000D_
<br>_x000D_
<input id="new-state" type="text" />_x000D_
<button type="button" id="btn-add-state">Set state value</button>
_x000D_
_x000D_
_x000D_

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


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.


$("#my_select").select2('destroy').empty().select2({data: [{id: 1, text: "new_item"}]});

In Select2 4.0.2

$("#yourId").append("<option value='"+item+"' selected>"+item+"</option>");
$('#yourId').trigger('change'); 

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to ajax

Getting all files in directory with ajax Cross-Origin Read Blocking (CORB) Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource Fetch API request timeout? How do I post form data with fetch api? Ajax LARAVEL 419 POST error Laravel 5.5 ajax call 419 (unknown status) How to allow CORS in react.js? Angular 2: How to access an HTTP response body? How to post a file from a form with Axios

Examples related to jquery-select2

How can I set the initial value of Select2 when using AJAX? Dynamically add item to jQuery Select2 control that uses AJAX How to set selected value of jquery select2? Styling of Select2 dropdown select boxes How to use placeholder as default value in select2 framework How can I disable selected attribute from select2() dropdown Jquery? Select2 open dropdown on focus How to use Select2 with JSON via Ajax request? Select2() is not a function jQuery select2 get value of select tag?