taxicala
taxicala

Reputation: 21769

Select2: Multiple select elements constrained

I am trying to achieve something and I can't find/decide what is the best way to do it, so i'm going to ask if somebody did this before or if select2 has something built in in order to achieve what I want.

Heres the thing: I have a number of select (multiple) elements in my DOM, lets say 5, all share the same options, but, If one of the selects has an option selected, I want the others to hide/remove/avoid being selected, I would like to constrain all selects in order to avoid having the same value selected in 2 different selects. I am not asking for a full code solution, I just need to know if someone already did it (if yes, would be nice to get it shared in order for future developers that stumble upon this can see the solution), or if select2 has the functionallity.

What I have done so far is:

       $('.constrainedSelect').each(function(i, select) {    
            var selectedValue = $(select).select2("val");
            var options = $('#allOptions').find('option').clone();

            if (selectedValue.length !== 0) {
                options.each(function(i, option) {
                    if($(select).find('option[value="' + $(option).val() + '"]').length !== 1) {
                        $(select).append(option);
                    }
                });
            } else {
                options.push($("<option />", {value: e.choice.id.trim(), text: e.choice.text.trim()})[0]);
                $(select).html(options);
            }
        });

But thats just a concept and its really buggy.

The version of select2 i'm using (and need to use, no time to change it in production yet) is Version: 3.5.2 Timestamp: Sat Nov 1 14:43:36 EDT 2014

Thanks in advance!

Upvotes: 1

Views: 2836

Answers (3)

taxicala
taxicala

Reputation: 21769

I have found a nice way to do this, if anyone was wondering how, I think this is a good approach but I would like to see comments and if somebody wants to improve my answer, feel free to copy the code and paste it in a separate answer, if the approach gets better I will accept that answer. Thanks guys for the help.

        var $selects = $(".constrainedSelects");
        $selects.on('change', function(e) {
            var selectedValues = $(this).select2('val');
            for (var i = 0; i < selectedValues.length; i++) {
                $selects.not(this).find("option[value='" + selectedValues[i] + "']").attr('disabled', true);
            }
        });

        $selects.on('select2-removed', function(e) {
            $selects.find("option[value='" + e.val + "']").attr('disabled', false);
        });

Here is a fiddle to show the result: http://jsfiddle.net/rv38f0v6/

Upvotes: 3

Paul Zepernick
Paul Zepernick

Reputation: 1462

 $(document).on('change', '.constrainedSelect', function() {
    var changedSelect = $(this);
    $(".constrainedSelect").not(changedSelect).select2("val", "").select2("enable", false)
});

I think something like this event listener would take care of it. It makes sure the val of all the others are empty and then disables them so they cannot be selected from.

How about this instead:

Working Fiddle

//setup trackign array and block duplicate selections
var selectedIds = [];
 $(document).on('select2-selecting', '.constrainedSelect', function(event) {
    var idx = $.inArray(event.val, selectedIds);
    if(idx === -1) {
        selectedIds.push(event.val);
    } else {
        event.preventDefault();
    }
});

//remove selected item from our tracking array
 $(document).on('select2-removed', '.constrainedSelect', function(event) {
    var idx = $.inArray(event.val, selectedIds);
    selectedIds.splice(idx,1);
});

Upvotes: -2

Kalish
Kalish

Reputation: 833

Please See if this helps! this is a jquery validation method to avoid same values in different select boxes.

 $.validator.addMethod("valOption", function(value, element) {
         var curValue,
             allElems,
             counter,
             totalCount = 0;

         curValue = value;
         allElems = $('#myPage select');
         for (counter = 0; counter < allElems.length; counter = counter + 1) {
             if (curValue === allElems.eq(counter).val()) {
                 totalCount = totalCount + 1;
             }
         }
         if (totalCount === 1) {
             return this.optional(element) || (true);
         } else {
             return (false);
         }
     }, "Please select different option");

Upvotes: -1

Related Questions