Nick
Nick

Reputation: 1999

jQuery show/hide options from one select drop down, when option on other select dropdown is slected

I need to show/hide options on one select drop down dependant on another select drop down options.

The code below shows what I am trying to achieve.

If the 'column_select' select menu option is set to '1 column' then the 'layout_select' select menu must display only the 'none' option.

If the 'column_select' select menu option is set to '2 column' then the 'layout_select' select menu must display only the 'layout 1' and 'layout 2' options.

If the 'column_select' select menu option is set to '3 column' then the 'layout_select' select menu must display only the 'layout 3', 'layout 4' and 'layout 5' options.

<select name="column_select" id="column_select">
    <option value="col1">1 column</option>
    <option value="col2">2 column</option>
    <option value="col3">3 column</option>
</select>

<select name="layout_select" id="layout_select">
    <!--Below shows when '1 column' is selected is hidden otherwise-->
    <option value="col1">none</option>

    <!--Below shows when '2 column' is selected is hidden otherwise-->
    <option value="col2_ms">layout 1</option> 
    <option value="col2_sm">layout 2</option>

    <!--Below shows when '3 column' is selected is hidden otherwise-->
    <option value="col3_mss">layout 3</option>
    <option value="col3_ssm">layout 4</option>
    <option value="col3_sms">layout 5</option>
</select>

So far everything I have tried has failed abysmally.... I am new to jQuery. If anybody could please help it would be much appreciated. Thanks!

Upvotes: 27

Views: 185427

Answers (6)

RitchieD
RitchieD

Reputation: 1861

And in 2016.....I do this (which works in all browsers and does not create "illegal" html).

For the drop-down select that is to show/hide different values add that value as a data attribute.

<select id="animal">
    <option value="1" selected="selected">Dog</option>
    <option value="2">Cat</option>
</select>
<select id="name">
    <option value=""></option>
    <option value="1" data-attribute="1">Rover</option>
    <option value="2" selected="selected" data-attribute="1">Lassie</option>
    <option value="3" data-attribute="1">Spot</option>
    <option value="4" data-attribute="2">Tiger</option>
    <option value="5" data-attribute="2">Fluffy</option>
</select>

Then in your jQuery add a change event to the first drop-down select to filter the second drop-down.

$("#animal").change( function() {
    filterSelectOptions($("#name"), "data-attribute", $(this).val());
});

And the magic part is this little jQuery utility.

function filterSelectOptions(selectElement, attributeName, attributeValue) {
    if (selectElement.data("currentFilter") != attributeValue) {
        selectElement.data("currentFilter", attributeValue);
        var originalHTML = selectElement.data("originalHTML");
        if (originalHTML)
            selectElement.html(originalHTML)
        else {
            var clone = selectElement.clone();
            clone.children("option[selected]").removeAttr("selected");
            selectElement.data("originalHTML", clone.html());
        }
        if (attributeValue) {
            selectElement.children("option:not([" + attributeName + "='" + attributeValue + "'],:not([" + attributeName + "]))").remove();
        }
    }
}

This little gem tracks the current filter, if different it restores the original select (all items) and then removes the filtered items. If the filter item is empty we see all items.

Upvotes: 9

Bharat Parmar
Bharat Parmar

Reputation: 1880

Initialy both dropdown have same option ,the option you select in firstdropdown is hidden in seconddropdown."value" is custom attribute which is unique.

$(".seconddropdown option" ).each(function() {
    if(($(this).attr('value')==$(".firstdropdown  option:selected").attr('value') )){
        $(this).hide();
        $(this).siblings().show();
    }
});

Upvotes: 2

Jouke
Jouke

Reputation: 21

A litle late perhaps but I would suggest

$(document).ready(function() {
    var layout_select_html = $('#layout_select').html(); //save original dropdown list

    $("#column_select").change(function () {
        var cur_column_val = $(this).val(); //save the selected value of the first dropdown
        $('#layout_select').html(layout_select_html); //set original dropdown list back
        $('#layout_select').children('option').each(function(){ //loop through options
        if($(this).val().indexOf(cur_column_val)== -1){ //do your conditional and if it should not be in the dropdown list
           $(this).remove(); //remove option from list
        }
    });
});

Upvotes: 2

ipr101
ipr101

Reputation: 24236

Try -

$("#column_select").change(function () {
    $("#layout_select").children('option').hide();
    $("#layout_select").children("option[value^=" + $(this).val() + "]").show()
})  

If you were going to use this solution you'd need to hide all of the elements apart from the one with the 'none' value in your document.ready function -

$(document).ready(function() {
    $("#layout_select").children('option:gt(0)').hide();
    $("#column_select").change(function() {
        $("#layout_select").children('option').hide();
        $("#layout_select").children("option[value^=" + $(this).val() + "]").show()
    })
})

Demo - http://jsfiddle.net/Mxkfr/2

EDIT

I might have got a bit carried away with this, but here's a further example that uses a cache of the original select list options to ensure that the 'layout_select' list is completely reset/cleared (including the 'none' option) after the 'column_select' list is changed -

$(document).ready(function() {
    var optarray = $("#layout_select").children('option').map(function() {
        return {
            "value": this.value,
            "option": "<option value='" + this.value + "'>" + this.text + "</option>"
        }
    })

    $("#column_select").change(function() {
        $("#layout_select").children('option').remove();
        var addoptarr = [];
        for (i = 0; i < optarray.length; i++) {
            if (optarray[i].value.indexOf($(this).val()) > -1) {
                addoptarr.push(optarray[i].option);
            }
        }
        $("#layout_select").html(addoptarr.join(''))
    }).change();
})

Demo - http://jsfiddle.net/N7Xpb/1/

Upvotes: 46

Andrew Whitaker
Andrew Whitaker

Reputation: 126042

How about:

(Updated)

$("#column_select").change(function () {
    $("#layout_select")
        .find("option")
        .show()
        .not("option[value*='" + this.value + "']").hide();

    $("#layout_select").val(
        $("#layout_select").find("option:visible:first").val());

}).change();

(assuming the third option should have a value col3)

Example: http://jsfiddle.net/cL2tt/

Notes:

  • Use the .change() event to define an event handler that executes when the value of select#column_select changes.
  • .show() all options in the second select.
  • .hide() all options in the second select whose value does not contain the value of the selected option in select#column_select, using the attribute contains selector.

Upvotes: 9

rodneyrehm
rodneyrehm

Reputation: 13557

// find the first select and bind a click handler
$('#column_select').bind('click', function(){
    // retrieve the selected value
    var value = $(this).val(),
        // build a regular expression that does a head-match
        expression = new RegExp('^' + value),
        // find the second select
        $select = $('#layout_select);

    // hide all children (<option>s) of the second select,
    // check each element's value agains the regular expression built from the first select's value
    // show elements that match the expression
    $select.children().hide().filter(function(){
      return !!$(this).val().match(expression);
    }).show();
});

(this is far from perfect, but should get you there…)

Upvotes: 1

Related Questions