[javascript] How to dynamic filter options of <select > with jQuery?

<select >
<option value="something">something</option>
<option value="something_else">something else</option>
</select>
<input type="text" >

So that when user inputs something, only options with value matching the input will show.

This question is related to javascript jquery dom

The answer is


You can use select2 plugin for creating such a filter. With this lot's of coding work can be avoided. You can grab the plugin from https://select2.github.io/

This plugin is much simple to apply and even advanced work can be easily done with it. :)


using Aaron's answer, this can be the short & easiest solution:

function filterSelectList(selectListId, filterId)
{
    var filter = $("#" + filterId).val().toUpperCase();

    $("#" + selectListId + " option").each(function(i){
       if ($(this).text.toUpperCase().includes(filter))
           $(this).css("display", "block");
       else
           $(this).css("display", "none");
    });
};

Just a minor modification to the excellent answer above by Lessan Vaezi. I ran into a situation where I needed to include attributes in my option entries. The original implementation loses any tag attributes. This version of the above answer preserves the option tag attributes:

jQuery.fn.filterByText = function(textbox) {
  return this.each(function() {
    var select = this;
    var options = [];
    $(select).find('option').each(function() {
      options.push({
          value: $(this).val(),
          text: $(this).text(),
          attrs: this.attributes, // Preserve attributes.
      });
    });
    $(select).data('options', options);

    $(textbox).bind('change keyup', function() {
      var options = $(select).empty().data('options');
      var search = $.trim($(this).val());
      var regex = new RegExp(search, "gi");

      $.each(options, function(i) {
        var option = options[i];
        if (option.text.match(regex) !== null) { 
            var new_option = $('<option>').text(option.text).val(option.value);
            if (option.attrs) // Add old element options to new entry
            {
                $.each(option.attrs, function () {
                    $(new_option).attr(this.name, this.value);
                    });
            }
            
            $(select).append(new_option);
        }
      });
    });
  });
};

A much simpler way nowadays is to use the jquery filter() as follows:

var options = $('select option');
var query = $('input').val();
options.filter(function() {
    $(this).toggle($(this).val().toLowerCase().indexOf(query) > -1);
});  

This is a simple solution where you clone the lists options and keep them in an object for recovery later. The scripts cleans out the list and add only the options that contains the input text. This should also work cross browser. I got some help from this post: https://stackoverflow.com/a/5748709/542141

Html

<input id="search_input" placeholder="Type to filter">
<select id="theList" class="List" multiple="multiple">

or razor

@Html.ListBoxFor(g => g.SelectedItem, Model.items, new { @class = "List", @id = "theList" })

script

<script type="text/javascript">
  $(document).ready(function () {
    //copy options
    var options = $('#theList option').clone();
    //react on keyup in textbox
    $('#search_input').keyup(function () {
      var val = $(this).val();
      $('#theList').empty();
      //take only the options containing your filter text or all if empty
      options.filter(function (idx, el) {
        return val === '' || $(el).text().indexOf(val) >= 0;
      }).appendTo('#theList');//add it to list
     });
  });
</script>

Slightly different to all the other but I think this is the most simple:

$(document).ready(function(){

    var $this, i, filter,
        $input = $('#my_other_id'),
        $options = $('#my_id').find('option');

    $input.keyup(function(){
        filter = $(this).val();
        i = 1;
        $options.each(function(){
            $this = $(this);
            $this.removeAttr('selected');
            if ($this.text().indexOf(filter) != -1) {
                $this.show();
                if(i == 1){
                    $this.attr('selected', 'selected');
                }
                i++;
            } else {
                $this.hide();
            }
        });
    });

});

I had a similar problem to this, so I altered the accepted answer to make a more generic version of the function. I thought I'd leave it here.

var filterSelectOptions = function($select, callback) {

    var options = null,
        dataOptions = $select.data('options');

    if (typeof dataOptions === 'undefined') {
        options = [];
        $select.children('option').each(function() {
            var $this = $(this);
            options.push({value: $this.val(), text: $this.text()});
        });
        $select.data('options', options);
    } else {
        options = dataOptions;
    }

    $select.empty();

    $.each(options, function(i) {
        var option = options[i];
        if(callback(option)) {
            $select.append(
                $('<option/>').text(option.text).val(option.value)
            );
        }
    });
};

I'm not sure why you have more than one option with the same value, but this works

_x000D_
_x000D_
$(document).ready(function() {_x000D_
  $('input').change(function() {_x000D_
    var filter = $(this).val();_x000D_
    $('option').each(function() {_x000D_
      if ($(this).val() == filter) {_x000D_
        $(this).show();_x000D_
      } else {_x000D_
        $(this).hide();_x000D_
      }_x000D_
      $('select').val(filter);_x000D_
    })_x000D_
  })_x000D_
})
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<select>_x000D_
   <option value="something1">something1</option>_x000D_
   <option value="something1">something1</option>_x000D_
   <option value="something2">something2</option>_x000D_
   <option value="something2">something2</option>_x000D_
   <option value="something2">something2</option>_x000D_
   <option value="something3">something3</option>_x000D_
   <option value="something3">something3</option>_x000D_
   <option value="something3">something3</option>_x000D_
</select>_x000D_
<input type="text" placeholder="something1">
_x000D_
_x000D_
_x000D_


Much simpler code then most of the other solutions. Look for the text (case insensitive) and use CSS to hide/show the contents. Much better than storing a copy of the data.

Pass into this method the id of the select box, and id of the input containing a filter.

function FilterSelectList(selectListId, filterId)
{
    var filter = $("#" + filterId).val();
    filter = filter.toUpperCase();

    var options = $("#" + selectListId + " option");
    for (var i = 0; i < options.length; i++)
    {
       if (options[i].text.toUpperCase().indexOf(filter) < 0)
           $(options[i]).css("display", "none");
       else
           $(options[i]).css("display", "block");
    }
};

Update Lessan's answer to also keep the attributes of the options.

This is my first time answering on Stack Overflow so not sure if I should edit his answer or create my own.

jQuery.fn.allAttr = function() {
  var a, aLength, attributes, map;
  if (!this[0]) return null;
  if (arguments.length === 0) {
    map = {};
    attributes = this[0].attributes;
    aLength = attributes.length;
    for (a = 0; a < aLength; a++) {
      map[attributes[a].name.toLowerCase()] = attributes[a].value;
    }
    return map;
  } else {
    for (var propin arguments[0]) {
      $(this[0]).attr(prop, arguments[0][prop]);
    }
    return this[0];
  }
};


jQuery.fn.filterByText = function(textbox) {
  return this.each(function() {
    var select = this;
    var options = [];
    $(select).find('option').each(function() {
      options.push({ value: $(this).val(), 
        text: $(this).text(), 
        allAttr: $(this).allAttr() });
    });
    $(select).data('options', options);

    $(textbox).bind('change keyup', function() {
      var search = $.trim($(this).val());
      var regex = new RegExp(search, "gi");

      $.each($(select).empty().data('options'), function(i, option) {
        if (option.text.match(regex) !== null) {
          $(select).append(
            $('<option>').text(option.text)
            .val(option.value)
            .allAttr(option.allAttr)
          );
        }
      });
    });
  });
};

Example HTML:

_x000D_
_x000D_
//jQuery extension method:_x000D_
jQuery.fn.filterByText = function(textbox) {_x000D_
  return this.each(function() {_x000D_
    var select = this;_x000D_
    var options = [];_x000D_
    $(select).find('option').each(function() {_x000D_
      options.push({_x000D_
        value: $(this).val(),_x000D_
        text: $(this).text()_x000D_
      });_x000D_
    });_x000D_
    $(select).data('options', options);_x000D_
_x000D_
    $(textbox).bind('change keyup', function() {_x000D_
      var options = $(select).empty().data('options');_x000D_
      var search = $.trim($(this).val());_x000D_
      var regex = new RegExp(search, "gi");_x000D_
_x000D_
      $.each(options, function(i) {_x000D_
        var option = options[i];_x000D_
        if (option.text.match(regex) !== null) {_x000D_
          $(select).append(_x000D_
            $('<option>').text(option.text).val(option.value)_x000D_
          );_x000D_
        }_x000D_
      });_x000D_
    });_x000D_
  });_x000D_
};_x000D_
_x000D_
// You could use it like this:_x000D_
_x000D_
$(function() {_x000D_
  $('select').filterByText($('input'));_x000D_
});
_x000D_
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<select>_x000D_
  <option value="hello">hello</option>_x000D_
  <option value="world">world</option>_x000D_
  <option value="lorem">lorem</option>_x000D_
  <option value="ipsum">ipsum</option>_x000D_
  <option value="lorem ipsum">lorem ipsum</option>_x000D_
</select>_x000D_
<input type="text">
_x000D_
_x000D_
_x000D_

Live demo here: http://www.lessanvaezi.com/filter-select-list-options/


<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<script language='javascript'>
jQuery.fn.filterByText = function(textbox, selectSingleMatch) {
  return this.each(function() {
    var select = this;`enter code here`
    var options = [];
    $(select).find('option').each(function() {
      options.push({value: $(this).val(), text: $(this).text()});
    });
    $(select).data('options', options);
    $(textbox).bind('change keyup', function() {
      var options = $(select).empty().scrollTop(0).data('options');
      var search = $.trim($(this).val());
      var regex = new RegExp(search,'gi');

      $.each(options, function(i) {
        var option = options[i];
        if(option.text.match(regex) !== null) {
          $(select).append(
             $('<option>').text(option.text).val(option.value)
          );
        }
      });
      if (selectSingleMatch === true && 
          $(select).children().length === 1) {
        $(select).children().get(0).selected = true;
      }
    });
  });
};

  $(function() {
     $('#selectorHtmlElement').filterByText($('#textboxFiltr2'), true);
  });
</script>

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

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 dom

How do you set the document title in React? How to find if element with specific id exists or not Cannot read property 'style' of undefined -- Uncaught Type Error adding text to an existing text element in javascript via DOM Violation Long running JavaScript task took xx ms How to get `DOM Element` in Angular 2? Angular2, what is the correct way to disable an anchor element? React.js: How to append a component on click? Detect click outside React component DOM element to corresponding vue.js component