3

I do have a form with 3 (or more) <select> elements with the class 'products-combo' and same <option> values.

Objective : Disable the particular <option> in every <select> if that <option> is selected in any of the <select> elements. And re enable the previous <option> if the selected option is changed.

I was able to do the disabling part with the below JQuery. But if I try to change my selected <option> after changing another <select> element then the previous selected <option> doesn't get enabled.

Steps to reproduce the problem in the snippet : Select options in the select boxes by the following order.

  1. select an option in first select box
  2. select an option in second select box
  3. select an option in third select box

For now everything works ok.

Now change selected option in the first select box.

After this, click on the second select or third select box. Here you can see that the new and old options of the first select option are disabled.

The expected result : When user changed the first selection option, then it is expected to re enable the previously selected option of first select element.

Scenario with example :

 1. In first select box "Product 1" option is selected
 2. In second select box "Product 2" option is selected
 3. In third select box "product 3" option is selected

Now Change the selected option in the first select box

select "Product 5" option in the first select box.

It is expected to disable "Product 5" option and enable "Product 1" in the second and third select boxes. But only the disabling is occurring. Re enabling of the "Product 1" is not happening.

What I have tried :

$('.products_combo')
    .not(this)
    .children('option[value="' + fieldValue + '"]')
    .prop('disabled', true);

It gives the same result as of the snippet.

Also if I add

.siblings().prop('disabled', false);

Then every other options get enabled. So this is not working.

How to fix this?

Snippet to test :

$('body').on("change", ".products-combo", function (evt) {
  var fieldValue  = $(this).val();
  $(this).siblings('.products-combo').children('option').each(function() {
    if ( $(this).val() === fieldValue ) {
      $(this).attr('disabled', true);   
    }
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="products-combo" name="product[]">
  <option>Select 1</option>
  <option value="1">Product 1</option>
  <option value="2">Product 2</option>
  <option value="3">Product 3</option>
  <option value="4">Product 4</option>
  <option value="5">Product 5</option>
</select>
<select class="products-combo" name="product[]">
  <option>Select 2</option>
  <option value="1">Product 1</option>
  <option value="2">Product 2</option>
  <option value="3">Product 3</option>
  <option value="4">Product 4</option>
  <option value="5">Product 5</option>
</select>
<select class="products-combo" name="product[]">
  <option>Select 3</option>
  <option value="1">Product 1</option>
  <option value="2">Product 2</option>
  <option value="3">Product 3</option>
  <option value="4">Product 4</option>
  <option value="5">Product 5</option>
</select>

A possible solution :

On .products-combo change event make an array of currently selected option values with <select> id as the key. And traverse through each select and disable or enable as per condition.

2 Answers 2

6

When looping all the options, if the option is not the selected one, you need to re-enable it.

const $selects = $(".products-combo");
$selects.on('change', function(evt) {
    // create empty array to store the selected values
    const selectedValue = [];
    // get all selected options and filter them to get only options with value attr (to skip the default options). After that push the values to the array.
    $selects.find(':selected').filter(function(idx, el) {
        return $(el).attr('value');
    }).each(function(idx, el) {
        selectedValue.push($(el).attr('value'));
    });
    // loop all the options
    $selects.find('option').each(function(idx, option) { 
        // if the array contains the current option value otherwise we re-enable it.
        if (selectedValue.indexOf($(option).attr('value')) > -1) {
            // if the current option is the selected option, we skip it otherwise we disable it.
            if ($(option).is(':checked')) {
                return;
            } else {
                $(this).attr('disabled', true);
            }
        } else {
            $(this).attr('disabled', false);
        }
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="products-combo" name="product[]">
  <option>Select 1</option>
  <option value="1">Product 1</option>
  <option value="2">Product 2</option>
  <option value="3">Product 3</option>
  <option value="4">Product 4</option>
  <option value="5">Product 5</option>
</select>
<select class="products-combo" name="product[]">
  <option>Select 2</option>
  <option value="1">Product 1</option>
  <option value="2">Product 2</option>
  <option value="3">Product 3</option>
  <option value="4">Product 4</option>
  <option value="5">Product 5</option>
</select>
<select class="products-combo" name="product[]">
  <option>Select 3</option>
  <option value="1">Product 1</option>
  <option value="2">Product 2</option>
  <option value="3">Product 3</option>
  <option value="4">Product 4</option>
  <option value="5">Product 5</option>
</select>

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for answering. But it's not working. Run my test condition. Select product 1 in first select box then select product 2 in second select box. Then you can see that in third select box product1 is enabled. Which shouldn't.
@ab_ab check here. If it's correct i will update the response. jsfiddle.net/7fsx86mn/39
Yes. The fiddle is working. Thank you. Add it to the answer. Please add some comments if you can, so that I can understand it.
0

    $('body').on('change', '.selectclass', function() {
               // create an array to store all the selected values
                values= []
                //iterate through all selects
                $('.selectclass').each(function() {
                 // push values to the array
                    values.push(this.value);
                });
                //iterate through all the options
                $('.selectclass').children('option').each(function() {
                    //check if valoe of the option exist in the array 
                    if (values.includes($(this).val())) {
                    //if the value of option exist in the array make this 
                    //option disabled 
                        $(this).attr('disabled', true);
                    } else {
                     //else enable this option
                        $(this).attr('disabled', false);
                    }
                });
            });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select name="cars" id="cars" class="selectclass" >
<option value="">Select 1</option>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="opel">Opel</option>
  <option value="audi">Audi</option>
</select>
<select name="cars" id="cars"  class="selectclass" >
<option value="">Select 1</option>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="opel">Opel</option>
  <option value="audi">Audi</option>
</select>
<select name="cars" id="cars"  class="selectclass" >
<option value="">Select 1</option>
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="opel">Opel</option>
  <option value="audi">Audi</option>
</select>

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.