Skip to content
Advertisement

JQuery : Disable multiple on multiple based on array of selected values

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.

Advertisement

Answer

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>
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement