Link to home
Start Free TrialLog in
Avatar of Tammu
Tammu

asked on

Disable selected option from one select box when selected in another select box

I have got 2 location select boxes and 2 color boxes. I wrote a jQuery code to disable a location option if it is selected from either of the location select boxes in the other.

The code I wrote it working for the location boxes but for some reason after the initial selection of an option in either of the location select boxes, the options from color boxes are also getting disabled.

This only happens when I try to select an option from a location select box second time

here is my full code and Jfiddle Link

What I am doing wrong. Thanks

<div class="pc-row">
	<div class="locations-colors pc-col quote-sizes">
	  <h4>Choose location below</h4>
	   <label for="location_one"><span>Location</span>
	    <select name="location_one" id="location_one">
         <option value="">choose location</option>
		 <option value="Full_Chest">Full Chest</option>
		 <option value="Full_Back">Full Back</option>
         <option value="Front_Left_Chest">Front Left Chest</option>
         <option value="Front_Right_Chest">Front Right Chest</option>
         <option value="Left_Sleeve">Left Sleeve</option>
		 <option value="Right_Sleeve">Right Sleeve</option>		 
        </select></label>
		
	</div>
	<div class="locations-colors pc-col quote-sizes">
	  <h4>Choose number of colors for location</h4>
	   <label for="color_one"><span>Number of Colors</span>
	    <select name="color_one" id="color_one">
         <option value="">choose colors</option>
		 <option value="0">One Color</option>
		 <option value="1">Two Colors</option>
         <option value="2">Three Colors</option>
         <option value="3">Four Colors</option>
        </select></label>
		
	</div>
	</div>
	
		<div class="pc-row">
	<div class="locations-colors pc-col quote-sizes">
	   <label for="location_two"><span>Location</span>
	    <select name="location_two" id="location_two">
         <option value="">choose location</option>
		 <option value="Full_Chest">Full Chest</option>
		 <option value="Full_Back">Full Back</option>
         <option value="Front_Left_Chest">Front Left Chest</option>
         <option value="Front_Right_Chest">Front Right Chest</option>
         <option value="Left_Sleeve">Left Sleeve</option>
		 <option value="Right_Sleeve">Right Sleeve</option>			 
        </select></label>
		
	</div>
	<div class="locations-colors pc-col quote-sizes">
	   <label for="color_two"><span>Number of Colors</span>
	    <select name="color_two" id="color_two">
         <option value="">choose colors</option>
		 <option value="1">One Color</option>
		 <option value="2">Two Colors</option>
         <option value="3">Three Colors</option>
         <option value="4">Four Colors</option>
        </select></label>
		
	</div>
	</div>

Open in new window


JavaScript

	$('select[name*="location"]').change(function() {
    var selectedOptions = $('select option:selected');
    $('select option').removeAttr('disabled');
    selectedOptions.each(function() {        
        var value = this.value;
        if (value !== ''){           
        var id = $(this).parent('select[name*="location"]').attr('id');
        var options = $('select:not(#' + id + ') option[value=' + value + ']');
        options.attr('disabled', 'true');
        }
    });
});	

Open in new window

Avatar of Rob
Rob
Flag of Australia image

Here I've updated your fiddle: https://jsfiddle.net/gzgy4toz/8/

essentially you were targeting all the <option> tags with $('option ...') so see the lines i've commented out for you

	$('select[name*="location"]').change(function() {
    var selectedOptions = $('select option:selected');
    $('select option').removeAttr('disabled');
    selectedOptions.each(function() {        
        var value = this.value;
        if (value !== ''){           
        var id = $(this).parent('select[name*="location"]').attr('id');
        var options = $('select:not(#' + id + ') option[value=' + value + ']');
        options.attr('disabled', 'true');
        }
    });
});	

Open in new window

Avatar of Tammu
Tammu

ASKER

Hi Rob

Thanks for replaying with a fix so quickly. I have one more question sir if one of the location select box selected is full chest i want to disable both front left chest and front right chest also.

Is this possible sir. Thanks and Appreciate it
it is, though you just need to include the logic.  What happens if you select left or right chest? does that disable anything?
Avatar of Tammu

ASKER

No sir nothing gets disabled only when full chest is selected disable front left and front right. Thanks again
Avatar of Tammu

ASKER

No sir nothing gets disabled only when full chest is selected disable front left and front right. Thanks again
SOLUTION
Avatar of Rob
Rob
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Just to add to Rob's solution above.

Firstly - don't use .attr('disabled', true) use .prop('disabled', true)

Then, I took a slightly different take on the problem and made it a bit more generic by adding some custom data attributes to the HTML and using those to manage the selects

I added data-linked="#location_???" to the drop downs where the ??? represents the id of the other
I added a data-exclude attribute to the option that specifies (in addition to itself) what should be disabled in the linked select. The attribute is optional - the value is assumed if the attribute is not specified.

CSS remains unchanged
HTML
<div class="pc-row">
  <div class="locations-colors pc-col quote-sizes">
    <h4>Choose location below</h4>
    <label for="location_one"><span>Location</span>
      <select name="location_one" id="location_one" data-linked="#location_two">
        <option value="">choose location</option>
        <option value="Full_Chest" data-exclude="Front_Left_Chest,Front_Right_Chest">Full Chest</option>
        <option value="Full_Back">Full Back</option>
        <option class="Full_Chest" value="Front_Left_Chest">Front Left Chest</option>
        <option class="Full_Chest" value="Front_Right_Chest">Front Right Chest</option>
        <option value="Left_Sleeve">Left Sleeve</option>
        <option value="Right_Sleeve">Right Sleeve</option>     
      </select></label>

  </div>
  <div class="locations-colors pc-col quote-sizes">
    <h4>Choose number of colors for location</h4>
    <label for="color_one"><span>Number of Colors</span>
      <select name="color_one" id="color_one">
        <option value="">choose colors</option>
        <option value="0">One Color</option>
        <option value="1">Two Colors</option>
        <option value="2">Three Colors</option>
        <option value="3">Four Colors</option>
      </select></label>

  </div>
</div>

<div class="pc-row">
  <div class="locations-colors pc-col quote-sizes">
    <label for="location_two"><span>Location</span>
      <select name="location_two" id="location_two" data-linked="#location_one">
        <option value="">choose location</option>
        <option value="Full_Chest" data-exclude="Front_Left_Chest,Front_Right_Chest">Full Chest</option>
        <option value="Full_Back">Full Back</option>
        <option class="Full_Chest" value="Front_Left_Chest">Front Left Chest</option>
        <option class="Full_Chest" value="Front_Right_Chest">Front Right Chest</option>
        <option value="Left_Sleeve">Left Sleeve</option>
        <option value="Right_Sleeve">Right Sleeve</option>       
      </select></label>

  </div>
  <div class="locations-colors pc-col quote-sizes">
    <label for="color_two"><span>Number of Colors</span>
      <select name="color_two" id="color_two">
        <option value="">choose colors</option>
        <option value="1">One Color</option>
        <option value="2">Two Colors</option>
        <option value="3">Three Colors</option>
        <option value="4">Four Colors</option>
      </select></label>

  </div>
</div>

Open in new window


jQuery
<script>
$(function() {
  $('select[name*="location"]').change(function() {
    // get the excluded options
    var exclude = ($('option:selected', $(this)).data('exclude') || '').split(',');

    // add the selected value by default
    exclude.push(this.value);

    // get the linked select id
    var linked = $($(this).data('linked'));
    
    // loop through options and set disabled PROPERTY
    // based on whether value is in exclude array
    $('option', $(this)).each(function(i, e) {
      var state = exclude.indexOf(e.value) != -1;
      $(this).prop('disabled', state);
    });
    
    $('option', linked).each(function(i, e) {
      var state = exclude.indexOf(e.value) != -1;
      $(this).prop('disabled', state);
    });
    
    // clear the linked select
    linked.val('');
  });   
});
</script>

Open in new window


Working sample here
Thanks Julian and yes prop('disabled', ...) should be used so that all facets (objects and interface) are correctly aligned.

I started down the more generic route too but pulled back when it was the only option, however it's good you've posted it as ultimately that would be the best way to code these types of problems as inevitably along comes a second scenario later and you have to build it anyway.

I still stick with bloating the page slightly with knockout (28kb or so... tiny!) so that this logic is easily represented within a JavaScript object.  Then these types of issues are relatively straightforward to implement: https://www.experts-exchange.com/articles/18468/Introducing-the-Knockout-JavaScript-Framework-MVVM.html
There is a watch-it in all solutions provided. If you select Full Chest from the first and then Full Back from the second - it clears the disabled from the Full Chest. This means we might need to rethink the problem.

While we are doing that here is a more efficient approach to my earlier post and a correction. The earlier post cleared the contents of the other select which is not what we want - the clearing should only happen if the other select contains a value that is now excluded.

To use the new approach requires that a class is added to the target selects to distinguish them from other selects on the page
I did this like so
<select name="location_two" id="location_two" data-linked="#location_one" class="linked-drop-down">

Open in new window

Based on this the jQuery changes to
<script>
$(function() {
  $('select[name*="location"]').change(function() {
    // get the excluded options
    var exclude = ($('option:selected', $(this)).data('exclude') || '').split(',');
	
    // add the selected value by default
	exclude.push(this.value);
	
    // get the linked select id
    var linked = $($(this).data('linked'));
    
    $('.linked-drop-down option').each(function(i,e) {
      var state = exclude.indexOf(e.value) != -1;
      $(this).prop('disabled', state);
    });
  });   
});
</script>

Open in new window


Still working on the solution that fixes the watch-it above.
Avatar of Tammu

ASKER

Thanks Rob & Julian,

I am gonna test both of them and see which will suit my project. I have total of 4 location select boxes, so I will expand on the code you guys have provided and see how it goes.

Thanks again
Avatar of Tammu

ASKER

Hi Rob,

I tested your solution sir but its resetting the values. What I mean is in the jFiddle, If I select full chest from the first location then it disables full chest, front left chest and front right chest from the second box, then I select Full back from second box, the full chest option in the second boxes get enabled again.

I managed to get it work by doing this but I am still stuck at disabling front left chest and front right chest when full chest option is selected in any of the location boxes.

here is my new jFiddle link

HTML CODE
	<div class="pc-row">
	<div class="locations-colors pc-col quote-sizes">
	  <h4>Choose location below</h4>
	   <label for="location_one"><span>Location</span>
	    <select name="location_one" id="location_one">
         <option value="">choose location</option>
		 <option value="Full_Chest">Full Chest</option>
		 <option value="Full_Back">Full Back</option>
         <option value="Front_Left_Chest">Front Left Chest</option>
         <option value="Front_Right_Chest">Front Right Chest</option>
         <option value="Left_Sleeve">Left Sleeve</option>
		 <option value="Right_Sleeve">Right Sleeve</option>		 
        </select></label>
		
	</div>
	<div class="locations-colors pc-col quote-sizes">
	  <h4>Choose number of colors for location</h4>
	   <label for="color_one"><span>Number of Colors</span>
	    <select name="color_one" id="color_one">
         <option value="">choose colors</option>
		 <option value="0">One Color</option>
		 <option value="1">Two Colors</option>
         <option value="2">Three Colors</option>
         <option value="3">Four Colors</option>
        </select></label>
		
	</div>
	</div>
	<br />
		<div class="pc-row">
	<div class="locations-colors pc-col quote-sizes">
	   <label for="location_two"><span>Location</span>
	    <select name="location_two" id="location_two">
         <option value="">choose location</option>
		 <option value="Full_Chest">Full Chest</option>
		 <option value="Full_Back">Full Back</option>
         <option value="Front_Left_Chest">Front Left Chest</option>
         <option value="Front_Right_Chest">Front Right Chest</option>
         <option value="Left_Sleeve">Left Sleeve</option>
		 <option value="Right_Sleeve">Right Sleeve</option>			 
        </select></label>
		
	</div>
	<div class="locations-colors pc-col quote-sizes">
	   <label for="color_two"><span>Number of Colors</span>
	    <select name="color_two" id="color_two">
         <option value="">choose colors</option>
		 <option value="1">One Color</option>
		 <option value="2">Two Colors</option>
         <option value="3">Three Colors</option>
         <option value="4">Four Colors</option>
        </select></label>
		
	</div>
	</div>
	<br />
			<div class="pc-row">
	<div class="locations-colors pc-col quote-sizes">
	   <label for="location_three"><span>Location</span>
	    <select name="location_three" id="location_three">
         <option value="">choose location</option>
		 <option value="Full_Chest">Full Chest</option>
		 <option value="Full_Back">Full Back</option>
         <option value="Front_Left_Chest">Front Left Chest</option>
         <option value="Front_Right_Chest">Front Right Chest</option>
         <option value="Left_Sleeve">Left Sleeve</option>
		 <option value="Right_Sleeve">Right Sleeve</option>			 
        </select></label>
		
	</div>
	<div class="locations-colors pc-col quote-sizes">
	   <label for="color_three"><span>Number of Colors</span>
	    <select name="color_three" id="color_three">
         <option value="">choose colors</option>
		 <option value="1">One Color</option>
		 <option value="2">Two Colors</option>
         <option value="3">Three Colors</option>
         <option value="4">Four Colors</option>
        </select></label>
		
	</div>
	</div>
	<br />
	<div class="pc-row">
	<div class="locations-colors pc-col quote-sizes">
	   <label for="location_four"><span>Location</span>
	    <select name="location_four" id="location_four">
         <option value="">choose location</option>
		 <option value="Full_Chest">Full Chest</option>
		 <option value="Full_Back">Full Back</option>
         <option value="Front_Left_Chest">Front Left Chest</option>
         <option value="Front_Right_Chest">Front Right Chest</option>
         <option value="Left_Sleeve">Left Sleeve</option>
		 <option value="Right_Sleeve">Right Sleeve</option>			 
        </select></label>
		
	</div>
	<div class="locations-colors pc-col quote-sizes">
	   <label for="color_four"><span>Number of Colors</span>
	    <select name="color_four" id="color_four">
         <option value="">choose colors</option>
		 <option value="1">One Color</option>
		 <option value="2">Two Colors</option>
         <option value="3">Three Colors</option>
         <option value="4">Four Colors</option>
        </select></label>
		
	</div>
	</div>

Open in new window


JavaScript
	$('select[name*="location"]').change(function() {
    var selectedOptions = $('select option:selected');
    $('select option').removeAttr('disabled');
    selectedOptions.each(function() {        
        var value = this.value;
        if (value !== ''){           
        var id = $(this).parent('select[name*="location"]').prop('id');
		var options = $('select[name*="location"]:not(#' + id + ') option[value=' + value + ']');
        options.prop('disabled', 'true');
        }
    });
});	

Open in new window


Thanks again and appreciate it
then I select Full back from second box, the full chest option in the second boxes get enabled again.
Is that not what you expected?  Full Chest is the only one that should affect others right?  Full Back should disable Full back in the other option or am I missing something?
We seem to have some duplicate threads running here. This question is linked to this one https://www.experts-exchange.com/questions/29010112/Based-on-each-selection-from-a-select-box-disable-same-option-in-3-other-select-boxes-and-show-another-select-box-based-on-value-selected.html?anchorAnswerId=42056927#a42056927

The solution is going to be the same.

I am posting my response from there here updated for the HTML in this thread.
HTML
<div class="pc-row">
  <div class="locations-colors pc-col quote-sizes">
    <h4>Choose location below</h4>
    <label for="location_one"><span>Location</span>
      <select name="location_one" id="location_one" data-linked="#location_two" class="linked-drop-down">
        <option value="">choose location</option>
        <option value="Full_Chest" data-exclude="Front_Left_Chest,Front_Right_Chest">Full Chest</option>
        <option value="Full_Back">Full Back</option>
        <option class="Full_Chest" value="Front_Left_Chest">Front Left Chest</option>
        <option class="Full_Chest" value="Front_Right_Chest">Front Right Chest</option>
        <option value="Left_Sleeve">Left Sleeve</option>
        <option value="Right_Sleeve">Right Sleeve</option>     
      </select></label>

  </div>
  <div class="locations-colors pc-col quote-sizes">
    <h4>Choose number of colors for location</h4>
    <label for="color_one"><span>Number of Colors</span>
      <select name="color_one" id="color_one">
        <option value="">choose colors</option>
        <option value="0">One Color</option>
        <option value="1">Two Colors</option>
        <option value="2">Three Colors</option>
        <option value="3">Four Colors</option>
      </select></label>

  </div>
</div>

<div class="pc-row">
  <div class="locations-colors pc-col quote-sizes">
    <label for="location_two"><span>Location</span>
      <select name="location_two" id="location_two" data-linked="#location_one" class="linked-drop-down">
        <option value="">choose location</option>
        <option value="Full_Chest" data-exclude="Front_Left_Chest,Front_Right_Chest">Full Chest</option>
        <option value="Full_Back">Full Back</option>
        <option class="Full_Chest" value="Front_Left_Chest">Front Left Chest</option>
        <option class="Full_Chest" value="Front_Right_Chest">Front Right Chest</option>
        <option value="Left_Sleeve">Left Sleeve</option>
        <option value="Right_Sleeve">Right Sleeve</option>       
      </select></label>

  </div>
  <div class="locations-colors pc-col quote-sizes">
    <label for="color_two"><span>Number of Colors</span>
      <select name="color_two" id="color_two">
        <option value="">choose colors</option>
        <option value="1">One Color</option>
        <option value="2">Two Colors</option>
        <option value="3">Three Colors</option>
        <option value="4">Four Colors</option>
      </select></label>

  </div>
</div>

Open in new window


jQuery
<script>
$(function() {
  $('select[name*="location"]').change(function() {
    // get the excluded options
    var exclude = [];
    $('.linked-drop-down option:selected').each(function(i,e) {
      var extra = ($(e).data('exclude') || '').split(',');
      extra.push(e.value);
      $.merge(exclude, extra);
    });
  
    // loop through options and set disabled PROPERTY
    // based on whether value is in exclude array
    var options = $('.linked-drop-down option');
      options.each(function(i, e) {
      // SPECIFICALLY CHECK FOR EMPTY OPTION SO WE HAVE A WAY
      // TO CLEAR SELECTION
      var state = e.value == '' ? false : exclude.indexOf(e.value) != -1;
      $(this).prop('disabled', state);
    });
  });   
});
</script>

Open in new window

Working sample here
Avatar of Tammu

ASKER

Hi Rob,

You are correct its working correctly. Sorry I have been stuck on this project so long I might be overthinking . Appreciate your help on this.

Thanks again
Avatar of Tammu

ASKER

Hi Rob,

Sorry again. After testing multiple times this is what I am seeing sir,

1) Say I select Full chest from location one box, then it disables, Full Chest, Front Left Chest and Front Right Chest from Location two and this works great

2) Now If I select Full back from Location two, then for some reason, Full Chest, Front Right Chest and Front Left Chest in location two gets re-enabled even though location one still has Full Chest selected

Thanks again
Avatar of Tammu

ASKER

Hi Julian,

I test your solution sir and works great but I noticed that for example

1) If I select full chest in location one, then it disables, Front Left Chest, Front Right Chest, Full Chest in other locations but its also disabling Front Left Chest, Front RIght Chest from the location where Full Chest is selected. How can we avoid that and only disable from other location boxes

Thanks again
Avatar of Tammu

ASKER

Here is my project so far on dev site.

Preview Link

I have implemented Julian Code, and When I select a location one with Full chest, only Full Chest is getting disabled. Not sure what I am missing

Thanks
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Tammu

ASKER

Hi Julian,

I appreciate your help in this a lot, But how I can extend the code to 4 locations. What I mean is data-linked for location one is #location_two and vice versa but how to include location 3 and 4 too sir

<select name="location_one" id="location_one" data-linked="#location_two" class="linked-drop-down">

Open in new window


What should be added to data-linked for location three and four.

Thanks
Avatar of Tammu

ASKER

Hi Julian,

I have updated the preview link sir and its not working, I am missing something from your working demo to mine not sure what it is.

Here is my updated link

Updated preview

Thanks
1. Solution is case sensitive
2. You have not included all your linked selects in the data-linked attribute of each drop down - I have filled out the attribute for the first one but you need to do for the other three - include id's of 3 other selects not including the one you are updating.
<select name="location_one" id="location_one" data-linked="#location_two,#location_three,#location_four" class="linked-drop-down">
  <option value="">choose location</option>
  <option value="Full_Chest" data-exclude="front_left_chest,front_right_chest">Full Chest</option>
  <option value="Full_Back">Full Back</option>
  <option value="Front_Left_Chest">Front Left Chest</option>
  <option value="Front_Right_Chest">Front Right Chest</option>
  <option value="Left_Sleeve">Left Sleeve</option>
  <option value="Right_Sleeve">Right Sleeve</option>		 
</select>

Open in new window


Specifically
data-exclude="front_left_chest,front_right_chest"

Open in new window

Has lower case values when the actual values it is targeting are capitalized.
Avatar of Tammu

ASKER

Thanks and appreciate it.

I have updated my preview link and made the changes as suggested ,

Update preview v2

 But here is whats happening now.  If I select a location from location one box, everything works great, its disabling the selected option in the 3 remaining boxes

If I select a location from Location One and a location from Location Two, everything works great, its disabling the selected option in the 2 remaining boxes
when select from 3 or 4 locations is here what's happening

I select Full Back from Location one ( full back is disabled not gets enabled in the location 2, 3 & 4)
I select Full Chest from Location two keeping Full Back in Location one ( Full chest, Front Left Chest, Front Right Chest gets disabled in only 3 but not in 1 and 4, also Full Back is still not disabled in 2, 3 and 4)

I select Left Sleeve from Location 3 keeping Full Chest in Location on, Full Back in Location 2 (
Full chest, Front Left Chest, Front Right Chest gets disabled in only 3 but not in 1 and 4,
 also Full Back is still not disabled in 2, 3 and 4 and only Left Sleeve is disabled in 4 but not in 1,2 and 3)

Thanks again
Avatar of Tammu

ASKER

Thanks guys. Appreciate your help in this regard.
You are welcome.
No problem. Thanks for the points