7

I am working on a project where I have a form that will have multiple 'select' inputs, all with the same set of options. I would like to use jquery to disable/hide an option in the rest of the 'select' inputs, if it has already been selected.

For example:

<select id="1">
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
</select>

<select id="2">
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
</select>

The user chooses 'Volvo' on the first select. I would like it removed from the second select.

Any info would be greatly appreciated.

Batfan
  • 7,966
  • 6
  • 33
  • 53
  • Which answer did you finally use pls? – netadictos Oct 29 '10 at 09:21
  • @netadictos - Yours ended up working the best but, it still was not exactly what I was looking for. I have decided to use Jquery UI to make draggable form values instead. Thanks for your help though :) – Batfan Oct 29 '10 at 15:20
  • Jquery UI is always a very modern way of doing things, I like. At least I think it's the solution to the question as it is described ;-) – netadictos Oct 29 '10 at 18:45

7 Answers7

6

Here there is the code to continue selecting and disabling all the times we want.

First thing is to enable every option, and then look at the selected values, and disable the options which coincides with the selected values.

These 2 steps are crucial because if you select again, the disabled values of before would continue disabled.

NEWEST VERSION

The more elegant way, where we use map() (in stackoverflow there is a good explanation about this method) and filter() jquery functions to do the job. Less lines, and I think same performance or better.

http://www.jsfiddle.net/dactivo/keDDr/

$("select").change(function()
 {

        $("select option").attr("disabled",""); //enable everything

     //collect the values from selected;
     var  arr = $.map
     (
        $("select option:selected"), function(n)
         {
              return n.value;
          }
      );

    //disable elements
    $("select option").filter(function()
    {

        return $.inArray($(this).val(),arr)>-1; //if value is in the array of selected values
     }).attr("disabled","disabled");   

});

NEW VERSION

I have edited my answer, this is my final version:

http://www.jsfiddle.net/dactivo/kNbWc/

$("select").change(function()
                   {

        $("select option").attr("disabled",""); //enable everything
        DisableOptions(); //disable selected values

                   });


function DisableOptions()
{
    var arr=[];
      $("select option:selected").each(function()
              {
                  arr.push($(this).val());
              });

    $("select option").filter(function()
        {

              return $.inArray($(this).val(),arr)>-1;
   }).attr("disabled","disabled");   

}

OLD VERSION

http://www.jsfiddle.net/AyxL3/

$("select").change(function()
                   {

        $("select option").attr("disabled",""); //enable everything
        DisableOptions(); //disable selected values

                   });


function DisableOptions()
{

    $("select option").filter(function()
        {
              var bSuccess=false; //will be our flag to know it coincides with selected value
              var selectedEl=$(this);
              $("select option:selected").each(function()
              {

                  if($(this).val()==selectedEl.val())
                  {
                       bSuccess=true; //it coincides we will return true;
                       return false; // this serves to break the each loop
                   }               

              });
              return bSuccess;
   }).attr("disabled","disabled");   

}
Community
  • 1
  • 1
netadictos
  • 7,602
  • 2
  • 42
  • 69
  • On the 'new version', when I select one option on the first select, its disabling 2 on the second one. On the 'newest one' its not disabling any of them. – Batfan Oct 23 '10 at 01:52
  • I found that this basically worked with the exception of the first line that enables all the fields. For me with Chrome in 2014 this just caused all the fields to all disable as soon as any dropdown is clicked on. The following fixed for me: $("#import_to_acf_matchoptions select option").prop("disabled", false);//enable everything – AdamJones Apr 02 '14 at 15:06
  • Thanks @AdamJones I have been trying to fix this for a while and just thought to read the comments. I am still having trouble with re-enabling things that were unselected but at least its not disabling everything like it was. – SeanBallentine Nov 16 '14 at 16:00
  • For some reason the all methods in here always disable all values for me each time i select a certain value. – Tamir Gilany Sep 20 '16 at 08:01
3

To hide them, use the following approach (since IE bug prevents using CSS "display" property setting to "none" on an OPTION):

-Store the original list of options in an array

-Have a function to build the select #x from an array, slipping previously selected items

-Assign an onchange handler for all selects which loops through all later selects and calls this function.

var option_value_order = {'volvo', 'saab', 'mercedes'};
var option_display_strings = new Array();
option_display_strings['volvo'] = 'Volvo'; 
//...

// Assume each of the selects' ID value is "select_1", "select_2" instead of "1", "2"
function redraw(selectNum) {
    var selectId = "select_" + selectNum;
    var s = document.getElementById(selectId);
    s.options.length = 0; // empty out
    var next = 0;
    for (var i = 0; i < option_value_order.length; i++) { 
        var skip = 0;
        for (var select_index = 0; select_index < selectNum; select_index++) {
            if (document.getElementById("select_"+select_index).selected == i)
                skip = 1;
            if (skip == 0) {
                var o = option_value_order[i];
                s.options[next] = o;
                // Don't recall how to set value different from option display, 
                // using option_display_strings[o] 
                next++;
            }
        }
    }
}

var total_selects = 2;

function change_later_selects(s) {
    var select_num = find_number(s.id); "this returns number 2 for "select_2" - homework
    for (var i = select_num + 1; i <= total_selects; i++) {
        redraw(i);
    }
}

And then the HTML

<select id="select_2" onchange="change_later_selects(this);">
  <option value="volvo">Volvo</option>
  <option value="saab">Saab</option>
  <option value="mercedes">Mercedes</option>
</select>
DVK
  • 126,886
  • 32
  • 213
  • 327
2

This question was the top google result for searching for an answer to this, so I'll post an updated answer here. This is almost the exact same as netadictos's answer, but works for disabling and re-enabling the select values and uses prop instead of attr. Verified working in Chrome 52.

    $("select").change(function()
    {
        $("select option").prop("disabled",""); //enable everything

        //collect the values from selected;
        var  arr = $.map
        (
            $("select option:selected"), function(n)
            {
                return n.value;
            }
        );

        //disable elements
        $("select option").filter(function()
        {
            return $.inArray($(this).val(),arr)>-1; //if value is in the array of selected values
        }).prop("disabled","disabled");

        //re-enable elements
        $("select option").filter(function()
        {
            return $.inArray($(this).val(),arr)==-1; //if value is not in the array of selected values
        }).prop("disabled","");
    }).trigger("change"); // Trigger the change function on page load. Useful if select values are pre-selected.
2

Here's a working example:

http://jsfiddle.net/aNxBy/

With your data, you have to do this:

$(document).ready(function() {
    $('select').change(function() {
        $('option[value=' + $(this).val() + ']').attr('disabled', 'disabled');
    });
});

Be mindful, however, of the fact that this won't disable the disable after you've changed it to another value. I didn't add this in here because you didn't specify exactly what you needed to do after you disabled the option...really it could be a number of possible scenarios.

One thing you could do is to cycle through all relevant select elements when the change event fires, find the values of all the selected options, and disable where appropriate.

treeface
  • 13,270
  • 4
  • 51
  • 57
  • How would I go about disabling the 'disable'? Say if the user changed their mind on the value they selected? – Batfan Oct 23 '10 at 01:54
  • How would I go about adding that to the code? I'm no jquery pro and still having a little trouble figuring out exactly how the current code is applying the 'disabled' attribute – Batfan Oct 23 '10 at 22:14
  • Please look at this when you get a sec. I'm not quite sure how to implement the remove attribute feature. I am going to end up using about 14-16 select tags. – Batfan Oct 25 '10 at 21:17
1

you could do something like

var curSelected = $('#1 option:selected').val();
$('#2 option[value="'+curSelected+'"]').remove()

(of course you could directly use $(this) if you plan to add the change to the options itself through the change handler)

Of course this won't work backwards :)

In that case I suggest you to build your options directly with JavaScript so that you have the complete blueprint from which remove elements when needed, before substituting them to various select

Jack
  • 131,802
  • 30
  • 241
  • 343
1

Take a look at this. It:

  1. gets the ID of the dropdown you just changed
  2. loops through all the select lists
  3. delete the item you just selected from all the other lists
Kshitij Parajuli
  • 349
  • 2
  • 12
1
$(document).ready(function() {
    $('#1').change(function() {
        $('option.hidden').removeClass('hidden')
        $('#2 option[value=' + $(this).val() + ']').addClass('hidden');
    });
    $('#2').change(function() {
        $('option.hidden').removeClass('hidden')
        $('#1 option[value=' + $(this).val() + ']').addClass('hidden');
    });
});

Make sure you have in css

.hidden {display:none}

Andrew Jackman
  • 13,781
  • 7
  • 35
  • 44