Search code examples
javascriptjquerybootstrap-multiselect

Bootstrap multiselect - Select none or max one of each group


I use bootsrtrap multiselect and with the below I can select none or max one of the options available:

<select id="select-records" multiple="multiple">
    <option value="50203_0">50203 - 0</option>
    <option value="50203_50">50203 - 50</option>
    <option value="50203_500">50203 - 500</option>
</select>

// Multiselect
$('#select-records').multiselect({
    maxHeight: 400,
    buttonWidth: '100%',
    onChange: function(element, checked) {
        var getValue = $('#select-records').val();
        console.log(getValue);
        if (getValue) {
            getValue = getValue.filter(function(item) {
                    return item !== ''+element.val()+''
            })
            $("#select-records").multiselect('deselect', ''+getValue +'');
            $("#select-records").multiselect('select', element.val());
        }
    }                   
});

Now I want to have further groups in the select options available ... like e.g.

<select id="select-records" multiple="multiple">
    <option value="50203_0">50203 - 0</option>
    <option value="50203_50">50203 - 50</option>
    <option value="50203_500">50203 - 500</option>
    <option value="60113_0">60113 - 0</option>
    <option value="60113_20">60113 - 50</option>
    <option value="60113_400">60113 - 500</option>
    <option value="70308_0">70308 - 0</option>
    <option value="70308_40">70308 - 50</option>
    <option value="70308_800">70308 - 500</option>
    /* .... Infinit additional groups */                
</select>

How do I need to alter the onChange of the multiselect to allow either none or max one option of each group (Group: 50203 or 60113 or 70308)?


Solution

  • You can do it like this:

    $('#select-records').multiselect({
      maxHeight: 400,
      buttonWidth: '100%',
      onChange: function (element, checked) {
        // If an element was just checked
        if (checked) {
          // Get its value
          var newValue = element.val();
          // And its group
          var newGroup = newValue.split('_')[0];
          // Get all checked values
          var checkedValues = this.$select.val();
          // Find one with the same group but different value
          var valueToDeselect = checkedValues.find(function (v) {
            return v.split('_')[0] === newGroup && v !== newValue;
          });
          // If we find one, deselect it
          if (valueToDeselect !== undefined) {
            this.$select.multiselect('deselect', '' + valueToDeselect);
          }
        }
      }
    });
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/css/bootstrap-multiselect.css">
    <script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.15/js/bootstrap-multiselect.min.js"></script>
    
    <select id="select-records" multiple="multiple" class="form-control">
        <option value="50203_0">50203 - 0</option>
        <option value="50203_50">50203 - 50</option>
        <option value="50203_500">50203 - 500</option>
        <option value="60113_0">60113 - 0</option>
        <option value="60113_20">60113 - 50</option>
        <option value="60113_400">60113 - 500</option>
        <option value="70308_0">70308 - 0</option>
        <option value="70308_40">70308 - 50</option>
        <option value="70308_800">70308 - 500</option>
    </select>

    Bonus: By using this.$select instead of $('#select-records') inside your onChange callback, you can make your code reusable, with multiple selects on the same page