Praveen Kumar Purushothaman
Praveen Kumar Purushothaman

Reputation: 167192

Disable options based on previous selects

I have four <select> tags. They are as follows:

<select name="" id="a">
    <option value="0">Select</option>
    <option value="1">Milk</option>
    <option value="2">Eggs</option>
    <option value="3">Cheese</option>
    <option value="4">Butter</option>
    <option value="5">Pizza</option>
</select>
<select name="" id="b">
    <option value="0">Select</option>
    <option value="1">Milk</option>
    <option value="2">Eggs</option>
    <option value="3">Cheese</option>
    <option value="4">Butter</option>
    <option value="5">Pizza</option>
</select>
<select name="" id="c">
    <option value="0">Select</option>
    <option value="1">Milk</option>
    <option value="2">Eggs</option>
    <option value="3">Cheese</option>
    <option value="4">Butter</option>
    <option value="5">Pizza</option>
</select>
<select name="" id="d">
    <option value="0">Select</option>
    <option value="1">Milk</option>
    <option value="2">Eggs</option>
    <option value="3">Cheese</option>
    <option value="4">Butter</option>
    <option value="5">Pizza</option>
</select>

These four are supposed to be having unique selections, although they have the same set of items. So using jQuery, how do I disable the options that are already selected? To be precise, I need to have four values taken from the <select> tag.

Solution and Problem

The current problem has a solution, but there's a limitation in it. Check my answer for the solution.

This solution is not scalable. If there are four <select>s, there should be four variables and the manual process to make them is tedious. Expecting a better solution.

Upvotes: 4

Views: 3859

Answers (4)

billyonecan
billyonecan

Reputation: 20260

Each time a select changes, just loop over each one, and then disable the option in all other selects where the value matches:

$('select').on('change', function() {

    /* enable any previously disabled options */
    $('option[disabled]').prop('disabled', false);

    /* loop over each select */
    $('select').each(function() {

       /* for every other select, disable option which matches this this.value */
       $('select').not(this).find('option[value="' + this.value + '"]').prop('disabled', true); 

    });

});

Here's a fiddle

Upvotes: 3

raddevus
raddevus

Reputation: 9077

This is where you really need a model for the data. Behind the scenes you would simply have an object which contains the list of items and a bool for whether or not the item was selected. Then, each option list would be tied to that list. Each one would only display the item in its list if the item's bool value was false.

var allItems = [{item:"eggs",isSelected:false}, 
      {item:"pizza",isSelected:false},
      {item:"cheese",isSelected:false},
      {item:"milk",isSelected:false} ];

All of the options controls are tied to that one list. When loading the items into the options control there is javascript which checks each value to see if isSelected is false. Only if it is false does the option control show the item in its list.

This would be much easier in Angular.

Upvotes: 0

ZiNNED
ZiNNED

Reputation: 2650

Not sure I fully understand your question, but you could do something like this:

HTML

<select>
    <option value="0">Select</option>
    <option value="1">Milk</option>
    <option value="2">Eggs</option>
    <option value="3">Cheese</option>
    <option value="4">Butter</option>
    <option value="5">Pizza</option>
</select>
<select>
    <option value="0">Select</option>
    <option value="1">Milk</option>
    <option value="2">Eggs</option>
    <option value="3">Cheese</option>
    <option value="4">Butter</option>
    <option value="5">Pizza</option>
</select>
<select>
    <option value="0">Select</option>
    <option value="1">Milk</option>
    <option value="2">Eggs</option>
    <option value="3">Cheese</option>
    <option value="4">Butter</option>
    <option value="5">Pizza</option>
</select>

JS

$(document).ready(function () {
    $("select").on("change", function () {
        // Enable all options
        $("option").prop("disabled", false);

        // Get an array of all current selections
        var selected = [];
        $("select").each(function () {
            selected.push($(this).val());
        });

        // Disable all selected options, except the current showing one, from all selects
        $("select").each(function () {
            for (var i = 0; i < selected.length; i++) {
                if (selected[i] != $(this).val()) {
                    $(this).find("option[value='" + selected[i] + "']").prop("disabled", true);
                }
            }
        });
    });
});

What you do is save the selected options in an array and disable these selected options in the other selects.

See this FIDDLE for an example.

Upvotes: 1

Praveen Kumar Purushothaman
Praveen Kumar Purushothaman

Reputation: 167192

If I have a known limited set of data, like I have four options here, I can do this way.

Pseudo Code

  1. Disable all the <select> tags and enable only the first.
  2. When a <select> is changed, enable the next <select>, and disable the option of the current <select>'s value.
  3. Save the current <select>'s value to the appropriate variable.
  4. When the next <select> is changed, disable the previous <select>, in order not to change the option selected.
  5. Repeat it for the rest, with increased number of values.

jQuery Code

$(document).ready(function(){
    var a, b, c, d;
    $("#b, #c, #d").prop("disabled", true);
    $("#a").change(function(){
        a = $(this).val();
        $("#b").find('option[value="' + a + '"]').prop("disabled", true);
        $("#b").prop("disabled", false);
    });
    $("#b").change(function(){
        b = $(this).val();
        $("#a").prop("disabled", true);
        $("#c").find('option[value="' + a + '"]').prop("disabled", true);
        $("#c").find('option[value="' + b + '"]').prop("disabled", true);
        $("#c").prop("disabled", false);
    });
    $("#c").change(function(){
        c = $(this).val();
        $("#a").prop("disabled", true);
        $("#b").prop("disabled", true);
        $("#d").find('option[value="' + a + '"]').prop("disabled", true);
        $("#d").find('option[value="' + b + '"]').prop("disabled", true);
        $("#d").find('option[value="' + c + '"]').prop("disabled", true);
        $("#d").prop("disabled", false);
    });
    $("#d").change(function(){
        d = $(this).val();
        $("#a").prop("disabled", true);
        $("#b").prop("disabled", true);
        $("#c").prop("disabled", true);
    });
    $("#reset").click(function(){
        $("#a").prop("disabled", false);
        $("#b, #c, #d").prop("disabled", true);
        $("#a, #b, #c, #d").val(0);
        return false;
    });
});

Problem with this Solution:

This solution is not scalable. If there are four <select>s, there should be four variables and the manual process to make them is tedious. Expecting a better solution.

Fiddle: http://jsfiddle.net/praveenscience/D5ZSk/

Upvotes: 1

Related Questions