Matt
Matt

Reputation: 5651

Maintain a set of select drop down lists using Javascript

I have a set of drop down lists (8 in all). All drop downs have the same set of drop down options available to them. However the business requirement is to make sure that the user cannot select the same option more than once.

Looking at the problem, at first it appears simple but it's rapidly becoming lots of code. However it seems like a relatively common problem. Does anyone know of a solution, have any tips on how to do this without writing reams of Javascript. Some sort of reusable jquery plugin might be handy for this too. Does one exist?

One issue is that when a select item is chosen, it then becomes unavailable to the other select lists. The item is removed from the other select drop downs. When it becomes available again (a drop down changes) it needs to be inserted at the correct point in the list (the drop down options have an order). This is the bit where my solution has started to get quite complex.

Upvotes: 0

Views: 1811

Answers (2)

Goran Mottram
Goran Mottram

Reputation: 6304

Personally, the way I'd implement it is to have a "master" drop down containing all possible options, simply for the purpose of caching. These options are then replicated in each of the "slave" drop downs. Whenever any slave drop down is changed, they're all re-populated again to ensure that no two drop downs can share the same selected value.

For the purpose of demonstration, I've only worked with 3 drop down lists in the code below, but it should scale up pretty easily. Just add mode drop downs and make sure they contain the attribute class="slave".

Also, if you want any of the options to be immune from being removed, so that it's possible to exist in all of your slave drop downs (such as the default option in the code below), just add the attribute class="immune" to the option tag in the master drop down.

<script type="text/javascript">

    // document - on load
    $(document).ready(function() {

        // initially populate all the drop downs
        PopulateAllDropDowns();

        // populate all drop downs on each subsequent change
        $('select.slave').change(function(){
            PopulateAllDropDowns();
        });

    });

    function PopulateAllDropDowns()
    {
        // populate all the slave drop downs
        $('select.slave').each(function(index){
            PopulateDropDown($(this).attr('id'));
        });
    }

    function PopulateDropDown(id)
    {
        // preserve the selected value
        var selectedValue = $('#'+id).val();

        // clear current contents
        $('#'+id).html('');

        // attempt to add each option from the master drop down
        $('select#ddlTemplate').children('option').each(function(index){

            // scope-safe var
            var masterOptionValue = $(this).val();              

            // check if option is in use in another slave drop down, unless it's immune
            var optionInUse = false;
            if (!$(this).hasClass("immune"))
            {
                $('select.slave option:selected').each(function(index){
                    if (masterOptionValue == $(this).val() )
                        optionInUse = true;
                });
            }               

            // if it's not in use, add it to this slave drop down
            if (!optionInUse)
            {
                // create new option
                var newOption = $('<option></option>').val($(this).val()).html($(this).text());

                // ensure selected value is preserved, if applicable
                if (selectedValue == $(this).val())
                    newOption.attr('selected', 'selected')

                // add the option                   
                $('#'+id).append(newOption);
            }

        });
    }       
</script>

 

<form>

    <!-- master drop down -->
    <select id="ddlTemplate" class="master" style="display:none">
        <option value="" class="immune">Select ...</option>
        <option value="a">Option A</option>
        <option value="b">Option B</option>
        <option value="c">Option C</option>
        <option value="d">Option D</option>
        <option value="e">Option E</option>
    </select>

    <!-- slave drop downs -->
    <select id="ddlOne" class="slave"></select>
    <select id="ddlTwo" class="slave"></select>
    <select id="ddlThree" class="slave"></select>

</form>

Hope that helps.

Upvotes: 2

Gabriel Gartz
Gabriel Gartz

Reputation: 2870

The simplest way to do what you want is binding a function in the select event from dropdown list that filter content from all other dropdowns and remove or disable the options with value already selected.

To keep the order from your list, cache the options list in array, then you can remove and add in the right position, or remove all options and re-add the current possible options.

If you want re-select the cached already chosen options, and you don't lose anything.

Upvotes: 0

Related Questions