107

I have an object with key/value pairs of options I want to hide/remove from a select list. Neither of the following option selectors work. What am I missing?

$.each(results['hide'], function(name, title) {                     
  $("#edit-field-service-sub-cat-value option[value=title]").hide();
  $("#edit-field-service-sub-cat-value option[@value=title]").hide();
}); 
Kara
  • 6,115
  • 16
  • 50
  • 57
hitfactory
  • 2,896
  • 5
  • 24
  • 22
  • 12
    are you sure the accepted answer works x-browser ;) I would hate anybody else to find this q&a through google and go away with the wrong impression! – redsquare Aug 13 '09 at 12:36
  • @redsquare - that's exactly why I posted a link to another question about hiding option elements in a select not being cross browser :) – Russ Cam Aug 13 '09 at 13:09
  • possible duplicate of [jQuery disable SELECT options based on Radio selected (Need support for all browsers)](http://stackoverflow.com/questions/877328/jquery-disable-select-options-based-on-radio-selected-need-support-for-all-brow) – Liam Nov 26 '13 at 16:27
  • I found that you also have to deselect the selected element if it is hidden after hide() is called in Chrome 57.0 – omarjebari Apr 12 '17 at 02:29

25 Answers25

144

For what it's worth, the second form (with the @) doesn't exist in jQuery 1.3. The first isn't working because you're apparently expecting variable interpolation. Try this:

$("#edit-field-service-sub-cat-value option[value=" + title + "]").hide();

Note that this will probably break in various hideous ways if title contains jQuery selector metacharacters.

chaos
  • 122,029
  • 33
  • 303
  • 309
  • 56
    Hiding options is *not* cross-browser compatible. – mpen Mar 28 '11 at 23:04
  • 1
    Putting single quotes woudl solve most jquery metacharacter issues – peterjwest Aug 16 '11 at 09:03
  • 12
    [Here is an answer that works cross browser](http://stackoverflow.com/a/878331/159341) - with an example [here](http://jsbin.com/anoci) – Tr1stan Dec 07 '11 at 08:39
  • This concept helped me for another solution. Thanks – Ajay Kumar Jul 11 '18 at 10:26
  • By weary when hiding as often this wont update the selected value. You'll need to select a new option after its hidden. If you're working in optgroup gets tricky traversing the DOM. – png Sep 14 '18 at 21:34
81

You cannot do this x-browser. If I recall ie has issues. The easiest thing to do is keep a cloned copy of the select before you remove items, this allows you to easily remove and then append the missing items back.

redsquare
  • 78,161
  • 20
  • 151
  • 159
  • 2
    getting options back won't be an issue as it's part of a dependent dropdown with ajax calls to the server to update the options each time the change. But is it a case of hide() not working in IE? – hitfactory Aug 13 '09 at 12:31
  • Indeed ie will not hide them. Not sure about ie8 but certainly one of the ie flavours doesnt work – redsquare Aug 13 '09 at 12:32
  • The pastebin link example doesn't hide the option in Chrome either – slolife Dec 11 '09 at 23:58
  • 5
    [Here is an answer that works cross browser](http://stackoverflow.com/a/878331/159341) - with an example [here](http://jsbin.com/anoci) - I've tested in IE6-9, Chrome and FF – Tr1stan Dec 07 '11 at 08:43
  • Please see my answer below, working in IE, FF, Chrome and Safari. It is the most flexible option (allowing for different values from displayed text). – Sablefoste Nov 20 '12 at 16:34
58

I found a better way, and it is very simple:

$("option_you_want_to_hide").wrap('<span/>')

To show again, just find that option(not span) and $("option_you_want_to_show").unwrap().

It was tested on Chrome and Firefox.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
William Herry
  • 1,430
  • 14
  • 26
  • 4
    You are an absolute genius! Just one row cross browser magic. – manudea Dec 20 '14 at 16:00
  • Cool. Handles the cross browser problem pretty well. – Subrat Pattnaik Jun 01 '15 at 11:01
  • 1
    I upvoted this one but it messes up if not implemented properly: for example you cannot use `$("select").val("0").trigger("change")`. Easier solution is [this](http://stackoverflow.com/a/32796511/1272001) – clod986 Sep 26 '15 at 11:11
  • Neat trick but throws off jQuery `.val()`. Use `$(selector)[0].value` if you need the value of the select – dlsso Sep 29 '15 at 21:03
  • Edit: in IE11 `.val()` still seems to work, may be only webkit browsers affected. – dlsso Sep 29 '15 at 21:46
  • This works OK, but is *painfully* slow in IE 11 if you're filtering oninput. My list had ~200 elements, and it would take a few seconds, per keystroke. Works great if you're filtering with a button onsubmit. – Tsar Bomba Nov 04 '15 at 13:48
  • generating invalid markup shouldn't be the goal, no? – Sam Jul 27 '16 at 12:38
  • 3
    You lose too much control using wrap/unwrap. it is easy to accidentally unwrap elements that haven't already been wrapped, hence stripping them of their parent element. Also it can mess up the css selectors. Using show/hide is better though you still need to remember to deselect any selected element as well with: $('selector-for-dropdown').val(''); – omarjebari Apr 12 '17 at 02:33
  • 1
    I liked the wrap/uwnrap solution. Just need to make sure that we don't double wrap ones that are already wrapped. Similar idea with unwrapped ones. – anon May 21 '18 at 18:51
  • @anon trying to handle that situation, my code is getting messy – pmiranda Nov 04 '19 at 15:03
48

Here is my spin, likely a bit faster due to native DOM methods

$.each(results['hide'], function(name, title) {                     
    $(document.getElementById('edit-field-service-sub-cat-value').options).each(function(index, option) {
      if( option.value == title ) {
        option.hidden = true; // not fully compatible. option.style.display = 'none'; would be an alternative or $(option).hide();
      }
    });
});
Caprica Six
  • 1,490
  • 12
  • 11
15

It CAN be done cross browser; it just takes some custom programming. Please see my fiddle at http://jsfiddle.net/sablefoste/YVMzt/6/. It was tested to work in Chrome, Firefox, Internet Explorer, and Safari.

In short, I have a hidden field, #optionstore, which stores the array sequentially (since you can't have Associative Arrays in JavaScript). Then when you change the category, it parses the existing options (first time through only) writes them to #optionstore, erases everything, and puts back only the ones associated with the category.

NOTE: I created this to allow different option values from the text displayed to the user, so it is highly flexible.

The HTML:

<p id="choosetype">
    <div>
        Food Category:
    </div>
    <select name="category" id="category" title="OPTIONAL - Choose a Category to Limit Food Types" size="1">
        <option value="">All Food</option>
        <option value="Food1">Fruit</option>
        <option value="Food2">Veggies</option>
        <option value="Food3">Meat</option>
        <option value="Food4">Dairy</option>
        <option value="Food5">Bread</option>
    </select>
    <div>
        Food Selection
    </div>
    <select name="foodType" id="foodType" size="1">
        <option value="Fruit1" class="sub-Food1">Apples</option>
        <option value="Fruit2" class="sub-Food1">Pears</option>
        <option value="Fruit3" class="sub-Food1">Bananas</option>
        <option value="Fruit4" class="sub-Food1">Oranges</option>
        <option value="Veg1" class="sub-Food2">Peas</option>
        <option value="Veg2" class="sub-Food2">Carrots</option>
        <option value="Veg3" class="sub-Food2">Broccoli</option>
        <option value="Veg4" class="sub-Food2">Lettuce</option>
        <option value="Meat1" class="sub-Food3">Steak</option>
        <option value="Meat2" class="sub-Food3">Chicken</option>
        <option value="Meat3" class="sub-Food3">Salmon</option>
        <option value="Meat4" class="sub-Food3">Shrimp</option>
        <option value="Meat5" class="sub-Food3">Tuna</option>
        <option value="Meat6" class="sub-Food3">Pork</option>
        <option value="Dairy1" class="sub-Food4">Milk</option>
        <option value="Dairy2" class="sub-Food4">Cheese</option>
        <option value="Dairy3" class="sub-Food4">Ice Cream</option>
        <option value="Dairy4" class="sub-Food4">Yogurt</option>
        <option value="Bread1" class="sub-Food5">White Bread</option>
        <option value="Bread2" class="sub-Food5">Panini</option>
    </select>
    <span id="optionstore" style="display:none;"></span>
</p>

The JavaScript/jQuery:

$(document).ready(function() {
    $('#category').on("change", function() {
        var cattype = $(this).val();
        optionswitch(cattype);
    });
});

function optionswitch(myfilter) {
    //Populate the optionstore if the first time through
    if ($('#optionstore').text() == "") {
        $('option[class^="sub-"]').each(function() {
            var optvalue = $(this).val();
            var optclass = $(this).prop('class');
            var opttext = $(this).text();
            optionlist = $('#optionstore').text() + "@%" + optvalue + "@%" + optclass + "@%" + opttext;
            $('#optionstore').text(optionlist);
        });
    }

    //Delete everything
    $('option[class^="sub-"]').remove();

    // Put the filtered stuff back
    populateoption = rewriteoption(myfilter);
    $('#foodType').html(populateoption);
}

function rewriteoption(myfilter) {
    //Rewrite only the filtered stuff back into the option
    var options = $('#optionstore').text().split('@%');
    var resultgood = false;
    var myfilterclass = "sub-" + myfilter;
    var optionlisting = "";

    myfilterclass = (myfilter != "")?myfilterclass:"all";

    //First variable is always the value, second is always the class, third is always the text
    for (var i = 3; i < options.length; i = i + 3) {
        if (options[i - 1] == myfilterclass || myfilterclass == "all") {
            optionlisting = optionlisting + '<option value="' + options[i - 2] + '" class="' + options[i - 1] + '">' + options[i] + '</option>';
            resultgood = true;
        }
    }
    if (resultgood) {
        return optionlisting;
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sablefoste
  • 4,032
  • 3
  • 37
  • 58
  • Could you please explain the use of the resultgood variable? We have removed its use because when the user has a filtered list and the user enters a character that means there are no items to display, an empty list is not actually displayed - the code continues to list the items that matched the search term without the extra character. Our use case differs slightly from the example - we use an input field to accept the entry of a search term. – B5A7 Feb 22 '18 at 01:20
  • The `resultgood` is simply a check to see if any `optionlisting` was added. if it was, the list of `";`. – Sablefoste Feb 22 '18 at 02:32
  • By the way, if I were to write this today, I probably wouldn't use class as the information carrier, but rather the `data` attribute; it is more semantically correct. – Sablefoste Feb 22 '18 at 02:33
  • Yes. We did the same. – B5A7 Feb 22 '18 at 05:26
14

This works in Firefox 3.0, but not in MSIE 8, nor in Opera 9.62:

jQuery('#destinations').children('option[value="1"]').hide();
jQuery('#destinations').children('option[value="1"]').css('display','none');

But rather hiding an option, one can simply disable it:

jQuery('#destinations').val('2'); 
jQuery('#destinations').children('option[value="1"]').attr('disabled','disabled');

The first of the the two lines above is for Firefox and pass focus to the 2nd option (assuming it has value="2"). If we omit it, the option is disabled, but the still displays the "enabled" option before we drop it down. Hence, we pass focus to another option to avoid this.

Blowsie
  • 40,239
  • 15
  • 88
  • 108
enthusiastic123
  • 141
  • 1
  • 3
5

Take a look at this question and the answers -

Disable select options...

Looking at your code, you may need to quote the attribute value

$("#edit-field-service-sub-cat-value option[value='title']").hide();

from jQuery attribute selectors

Quotes are optional in most cases, but should be used to avoid conflicts when the value contains characters like "]"

EDIT:

Just realised that you're getting the title from the function parameter, in which case the syntax should be

$("#edit-field-service-sub-cat-value option[value='" + title + "']").hide();
Community
  • 1
  • 1
Russ Cam
  • 124,184
  • 33
  • 204
  • 266
5

Your best bet is to set disabled=true on the option items you want to disable, then in CSS set

option:disabled {
    display: none;
}

That way even if the browser doesn't support hiding the disabled item, it still can't be selected.. but on browsers that do support it, they will be hidden.

eoleary
  • 414
  • 4
  • 11
4

In reference to redsquare's suggestion, I ended up doing this:

var selectItems = $("#edit-field-service-sub-cat-value option[value=" + title + "]").detach();

and then to reverse this:

$("#edit-field-service-sub-cat-value").append(selectItems);
Timothy Groote
  • 8,614
  • 26
  • 52
MadTurki
  • 343
  • 1
  • 6
  • 18
4

Having tested, the solutions posted above by various, including chaos, to hide elements do now work in the latest versions of Firefox (66.0.4), Chrome (74.0.3729.169) and Edge (42.17134.1.0)

$("#edit-field-service-sub-cat-value option[value=" + title + "]").hide();
$("#edit-field-service-sub-cat-value option[value=" + title + "]").show();

For IE, this does not work, however you can disable the option

$("#edit-field-service-sub-cat-value option[value=" + title + "]").attr("disabled", "disabled");
$("#edit-field-service-sub-cat-value option[value=" + title + "]").removeAttr("disabled");

and then force the selection of a different value.

$("#edit-field-service-sub-cat-value").val("0");

Note, for a disabled option, the val of the drop down will now be null, not the value of the selected option if it is disabled.

Steven Poole
  • 51
  • 1
  • 4
3

The problem is that Internet Explorer does not seem to support the hide and show methods for select options. I wanted to hide all options of my ddlReasonCode select which did not have the currently selected type as the value of the attribute "attType".

While the lovely Chrome was quite satisfied with:

//Hiding all options
            $("#ddlReasonCode").children().hide();
            //Showing only the relevant options
            $("#ddlReasonCode").children("option[atttype=\"" + CurrentType + "\"]").show();

This is what IE required (kids, don't try this at CHROME :-)):

//Hiding all options
            $("#ddlReasonCode option").each(function (index, val) {
                if ($(this).is('option') && (!$(this).parent().is('span')) && ($(this).atttype != CurrentType))
                    $(this).wrap('<span>').hide();
            });
            //Showing only the relevant options
            $("#ddlReasonCode option").each(function (index, val) {
                if (this.nodeName.toUpperCase() === 'OPTION') {
                    var span = $(this).parent();
                    var opt = this;
                    if ($(this).parent().is('span') && ((this).atttype == CurrentType)) {
                        $(opt).show();
                        $(span).replaceWith(opt);
                    }
                }
            });

I found that wrapping idea at http://ajax911.com/hide-options-selecbox-jquery/

Oranit Dar
  • 1,539
  • 18
  • 17
2

I was trying to hide options from one select-list based on the selected option from another select-list. It was working in Firefox3, but not in Internet Explorer 6. I got some ideas here and have a solution now, so I would like to share:

The JavaScript code

function change_fruit(seldd) {
    var look_for_id=''; var opt_id='';
    $('#obj_id').html("");
    $("#obj_id").append("<option value='0'>-Select Fruit-</option>");
    if(seldd.value=='0') {
        look_for_id='N';
    }
    if(seldd.value=='1'){
        look_for_id='Y';
        opt_id='a';
    }
    if(seldd.value=='2') {
        look_for_id='Y';
        opt_id='b';
    }
    if(seldd.value=='3') {
        look_for_id='Y';
        opt_id='c';
    }

    if(look_for_id=='Y') {
        $("#obj_id_all option[id='"+opt_id+"']").each(function() {
          $("#obj_id").append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
        });
    }
    else {
        $("#obj_id_all option").each(function() {
          $("#obj_id").append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");
        });
    }
}

The HTML

<select name="obj_id" id="obj_id">
    <option value="0">-Select Fruit-</option>
    <option value="1" id="a">apple1</option>
    <option value="2" id="a">apple2</option>
    <option value="3" id="a">apple3</option>
    <option value="4" id="b">banana1</option>
    <option value="5" id="b">banana2</option>
    <option value="6" id="b">banana3</option>
    <option value="7" id="c">Clove1</option>
    <option value="8" id="c">Clove2</option>
    <option value="9" id="c">Clove3</option>
</select>

<select name="fruit_type" id="srv_type" onchange="change_fruit(this)">
    <option value="0">All</option>
    <option value="1">Starts with A</option>
    <option value="2">Starts with B</option>
    <option value="3">Starts with C</option>
</select>

<select name="obj_id_all" id="obj_id_all" style="display:none;">
    <option value="1" id="a">apple1</option>
    <option value="2" id="a">apple2</option>
    <option value="3" id="a">apple3</option>
    <option value="4" id="b">banana1</option>
    <option value="5" id="b">banana2</option>
    <option value="6" id="b">banana3</option>
    <option value="7" id="c">Clove1</option>
    <option value="8" id="c">Clove2</option>
    <option value="9" id="c">Clove3</option>
</select>

It was checked as working in Firefox 3 and Internet Explorer 6.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Souvik
  • 21
  • 5
  • 5
    [According the W3C](http://www.w3.org/TR/html4/struct/global.html#h-7.5.2) the `id` attribute should be unique: _id = This attribute assigns a name to an element. This name must be unique in a document._ – Jasper Jan 13 '12 at 09:22
2

It seems that you also have to update the "selected" attribute. Otherwise the currently selected option may continue to display - although it probably will go away when you actually go to select an option (thats what it did for me): Try doing this:

$('#mySelector').children('option').hide();
$('#mySelector').children('option').removeAttr("selected"); //this may be overkill.
$('#mySelector').children('option[value="'+SelVal+'"]').show();  
$('#mySelector').children(':visible').attr('selected','selected'); //assuming that something is still on the list.
djoeberry
  • 21
  • 1
1

To avoid string concatenation you can use jQuery.grep

$($.grep($("#edit-field-service-sub-cat-value option"),
         function(n,i){
           return n.value==title;
         })
 ).hide()
rretzbach
  • 744
  • 1
  • 6
  • 16
1

Probably not as elegant or as reusable as a jquery plugin. but another approach is to simply save option elements and swap them out as required:

var SelectFilter = function ()
        {
            this.allOptions = $("#someSelect option");

            this.fooBarOptions= $("#someSelect option[value='foo']");
            this.fooBarOptions= this.fooBarOptions.add($("#someSelect option[value='bar']"));


            this.showFooBarOptions = function()
            {
                $("#someSelect option").remove();
                $("#someSelect").append(this.fooBarOptions);
            };
            this.showAllOptions = function()
            {
                $("#someSelect option").remove();
                $("#someSelect").append(this.allOptions);
            };



        };

do this to use the object:

var filterObject = new SelectFilter();
filterObject.showFooBarOptions (); 
Squibly
  • 335
  • 2
  • 7
1
$("option_you_want_to_hide").addClass('hidden')

Then, in your css make sure you have

.hidden{
    display:none;
}
clod986
  • 2,527
  • 6
  • 28
  • 52
1

I implemented a solution using a function that filters a combobox (<select>) based on custom data- attributes. This solution supports:

  • Having an <option> to show when the filter would leave the select empty.
  • Respects existing selected attributes.
  • <option> elements without the data-filter attribute are left untouched.

Tested with jQuery 2.1.4 and Firefox, Chrome, Safari and IE 10+.

This is the example HTML:

<select id="myCombobox">
  <option data-filter="1" value="AAA">Option 1</option>
  <option data-filter="1" value="BBB">Option 2</option>
  <option data-filter="2" value="CCC">Option 3</option>
  <option data-filter="2" value="DDD">Option 4</option>
  <option data-filter="3" value="EEE">Option 5</option>
  <option data-filter="3" value="FFF">Option 6</option>
  <option data-filter-emptyvalue disabled>No Options</option>
</select>

The jQuery code for the filtering:

function filterCombobox(selectObject, filterValue, autoSelect) {

  var fullData = selectObject.data("filterdata-values");
  var emptyValue = selectObject.data("filterdata-emptyvalue");

  // Initialize if first time.
  if (!fullData) {
    fullData = selectObject.find("option[data-filter]").detach();
    selectObject.data("filterdata-values", fullData);
    emptyValue = selectObject.find("option[data-filter-emptyvalue]").detach();
    selectObject.data("filterdata-emptyvalue", emptyValue);
    selectObject.addClass("filtered");
  }
  else {
    // Remove elements from DOM
    selectObject.find("option[data-filter]").remove();
    selectObject.find("option[data-filter-emptyvalue]").remove();
  }

  // Get filtered elements.
  var toEnable = fullData.filter("option[data-filter][data-filter='" + filterValue + "']");

  // Attach elements to DOM
  selectObject.append(toEnable);

  // If toEnable is empty, show empty option.
  if (toEnable.length == 0) {
    selectObject.append(emptyValue);
  }

  // Select First Occurrence
  if (autoSelect) {
    var obj = selectObject.find("option[selected]");
    selectObject.val(obj.length == 0 ? toEnable.val() : obj.val());
  }
}

To use it, you just call the function with the value you want to keep.

filterCombobox($("#myCombobox"), 2, true);

Then the resulting select will be:

<select id="myCombobox">
  <option data-filter="2" value="CCC">Option 3</option>
  <option data-filter="2" value="DDD">Option 4</option>
</select>

The original elements are stored by the data() function, so subsequent calls will add and remove the correct elements.

  • This is a great reusable solution, which is the only one I found which works on Safari. Thanks! – Echilon Feb 16 '17 at 09:58
0

Anybody stumbling across this question might also consider the use of Chosen, which greatly expands the capabilities of selects.

Charles Wood
  • 864
  • 8
  • 23
0

I know this question has been answered. But my requirement was slightly different. Instead of value I wanted to filter by text. So i modified the answer by @William Herry like this.

var array = ['Administration', 'Finance', 'HR', 'IT', 'Marketing', 'Materials', 'Reception', 'Support'];
if (somecondition) {
   $(array).each(function () {
       $("div#deprtmnts option:contains(" + this + ")").unwrap();
   });
}
else{
   $(array).each(function () {
       $("div#deprtmnts option:contains(" + this + ")").wrap('<span/>');
   });
}

This way you can use value also by replacing contains like this

 $("div#ovrcateg option[value=" + this + "]").wrap('<span/>');
jkjhse
  • 23
  • 9
0

For hide option in select use:

option_node.hidden = true; # For hide selcet item
option_node.hidden = false; # For show selcet item

Where option_node is HTMLOptionElement

P.S.: I do not use JQuery, but guessing, that it's will works:

$('.my_select option[value="my_cool_value"]').hidden = true
DAVIDhaker
  • 29
  • 6
0
 $('#id').val($('#id option:eq(0)').hide());

option:eq(0)-hide option at index '0' in select box.

Prashant Pimpale
  • 10,349
  • 9
  • 44
  • 84
Kiran
  • 11
0

The answer points out that @ is invalid for newer jQuery iterations. While that's correct, some older IEs still dont hide option elements. For anyone having to deal with hiding option elements in those versions affected, I posted a workaround here:

http://work.arounds.org/issue/96/option-elements-do-not-hide-in-IE/

Basically just wrap it with a span and replace on show.

meder omuraliev
  • 183,342
  • 71
  • 393
  • 434
0

You can show/hide with Value or Class name. Check the below link with working example.
Show/hide jquery chosen options with value or with class name.

Sandeep Sherpur
  • 2,418
  • 25
  • 27
0

$("#ddtypeoftraining option[value=5]").css("display", "none"); $('#ddtypeoftraining').selectpicker('refresh');

-1

I found it best to just remove the DOM completely.

$(".form-group #selectId option[value='39']").remove();

Cross browser compatible. Works on IE11 too

Vishal
  • 595
  • 7
  • 12