Does select2 dropdown support using ajax and allowing users to enter in new values?
Asked Answered
S

3

5

I am using select 2 and it works great. I have an example where as user is chosing from a dropdown via ajax (exactly like the Remote Data example listed in the link) but I want the user to be able to search as well as be able to type in a new value that doesn't exist on the back end.

I have this working on the multiselect but trying to see if there is the same support when using the single dropdown option?

Surfbird answered 12/12, 2016 at 1:20 Comment(2)
So what would be the desired behavior if the user enters a value that doesn't exist on the backend?Hanforrd
@Surfbird let me know if my answer helps...Laellaertes
L
7

From what I understand what you want is to use single select box with the ability for the user to select both from ajax source and also be able to free type the text.

Also you already have the ajax part working, The only thing you want to know is to add the free text typed by the user.

Here is a Working Fiddle Select2 plugin version used is 4.0.3

So working Snippet

$(".js-data-example-ajax").select2({
  language: {
    noResults: function() {
      return "No results found, <a id='newData' href='#' class='btn btn-xs btn-success'>Use the above text anyways</a>";
    }
  },
  ajax: {
    url: "https://api.github.com/search/repositories",
    dataType: 'json',
    delay: 250,
    data: function(params) {
      return {
        q: params.term, // search term
        page: params.page
      };
    },
    processResults: function(data, params) {
      params.page = params.page || 1;

      return {
        results: data.items,
        pagination: {
          more: (params.page * 30) < data.total_count
        }
      };
    },
    cache: true
  },
  escapeMarkup: function(markup) {
    return markup;
  },
  minimumInputLength: 1,
  templateResult: formatRepo,
  templateSelection: formatRepoSelection,
  createTag: function(params) {
    alert('create tag');
    return {
      id: params.term,
      text: params.term,
      newOption: true
    }
  }
});

$(document).on('click', '#newData', function() {
  var $select2 = $(".js-data-example-ajax");
  debugger;
  var newStateVal = $select2.siblings("span.select2-container").find("input.select2-search__field").val();
  if ($select2.find("option[value=" + newStateVal + "]").length) {
    $select2.val(newStateVal).trigger("change");
    $select2.select2('close');
  } else {
    // Create the DOM option that is pre-selected by default
    var newState = new Option(newStateVal, newStateVal, true, true);
    // Append it to the select
    $select2.append(newState).trigger('change');
    $select2.select2('close');
  }
});


function formatRepo(repo) {
  if (repo.loading) return repo.text;

  var markup = "<div class='select2-result-repository clearfix'>" +
    "<div class='select2-result-repository__avatar'><img src='" + repo.owner.avatar_url + "' /></div>" +
    "<div class='select2-result-repository__meta'>" +
    "<div class='select2-result-repository__title'>" + repo.full_name + "</div>";

  if (repo.description) {
    markup += "<div class='select2-result-repository__description'>" + repo.description + "</div>";
  }

  markup += "<div class='select2-result-repository__statistics'>" +
    "<div class='select2-result-repository__forks'><i class='fa fa-flash'></i> " + repo.forks_count + " Forks</div>" +
    "<div class='select2-result-repository__stargazers'><i class='fa fa-star'></i> " + repo.stargazers_count + " Stars</div>" +
    "<div class='select2-result-repository__watchers'><i class='fa fa-eye'></i> " + repo.watchers_count + " Watchers</div>" +
    "</div>" +
    "</div></div>";

  if (repo.newOption) {
    alert('adasdasddads');
  }

  return markup;
}

function formatRepoSelection(repo) {
  return repo.full_name || repo.text;
}
.select2-container {
  width: 100% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://select2.github.io/css/s2-docs.css" rel="stylesheet" />
<script src="https://select2.github.io/vendor/js/bootstrap.min.js"></script>
<script src="https://select2.github.io/dist/js/select2.full.js"></script>
<link href="https://select2.github.io/dist/css/select2.min.css" rel="stylesheet" />
<link href="https://select2.github.io/css/bootstrap.css" rel="stylesheet" />

<select class="js-data-example-ajax">
  <option value="3620194" selected="selected">select2/select2</option>
</select>

The changes required are.

1) We need to change the way the custom message No results found is shown. We need to have a option here saying add the typed text anyways. So Add the language option and with in this add the noResults option and give your custom message when no results are found. With in this custom message we add a button for which we write further logic to add this free typed text into our dropdown.

The code is as below

$(".js-data-example-ajax").select2({
  language: {
    noResults: function() {
      return "No results found, <a id='newData' href='#' class='btn btn-xs btn-success'>Use the above text anyways</a>";
    }
  },
  //... your other setting
};

with this settings added when ever there is no match found the result of the plugin is as enter image description here

2) Now with above change in place we need to add our extra code to handle the click event of the button to add this new option into our plugin. The code is as below.

$(document).on('click', '#newData', function() {
  var $select2 = $(".js-data-example-ajax");      
  var newStateVal = $select2.siblings("span.select2-container").find("input.select2-search__field").val();
  //Get the new value.
  if ($select2.find("option[value=" + newStateVal + "]").length) { //if already present just select it
    $select2.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
    $select2.append(newState).trigger('change');
    $select2.select2('close');
  }
});

With this, the plugin is capable of selecting value from ajax and also free type form. This is a single select example as that is what you wanted.

Hope this help!!

Laellaertes answered 18/12, 2016 at 7:14 Comment(2)
Thanks for the great answer. One issue now is the "value" in the dropdown is always an int (as i grabbing the data from a data base where a show a label and value but now if i support the idea of adding your own text then I need to change this to a string given the would be no int value on new entries. Given that, when I post my form, how would I detect that a user has entered in a new item (versus selected an existing item) outside of just seeing that the value in this field is not an int which feels a bit hacky given that a person in theory might have typed in a number as a new value?Surfbird
@Surfbird you can assign the value 0 for the newly typed string .. and while posting your form you can have a small if check to see if value is 0 and if it is.. add a additional parameter in your post data and pass in the new text too.. This should be fine right..Laellaertes
S
2

Here is the code :

$(".js-example-tags").select2({
  tags: true,
});

and remove multiple attribute from select2.

I hope this will work

Senatorial answered 16/12, 2016 at 10:42 Comment(0)
P
1

Here is example from select2 documentation

$(".js-data-example-ajax").select2({
  ajax: {
    url: "https://api.github.com/search/repositories",
    dataType: 'json',
    delay: 250,
    data: function (params) {
      return {
        q: params.term, // search term
        page: params.page
      };
    },
    processResults: function (data, params) {
      // parse the results into the format expected by Select2
      // since we are using custom formatting functions we do not need to
      // alter the remote JSON data, except to indicate that infinite
      // scrolling can be used
      params.page = params.page || 1;

      return {
        results: data.items,
        pagination: {
          more: (params.page * 30) < data.total_count
        }
      };
    },
    cache: true
  },
  escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
  minimumInputLength: 1,
  templateResult: formatRepo, // omitted for brevity, see the source of this page
  templateSelection: formatRepoSelection // omitted for brevity, see the source of this page
});
Prober answered 22/12, 2016 at 19:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.