Search code examples
bootstrap-multiselect

Bootstrap Multiselect filtering values based on another dropdown


I'm working on cascading the multi-select based on the values of the data-attributes on another.

I have this method which is called inside the onChanged event of the parent. By parent I mean what to filter the child by i.e

  • Parent = Department Multiselect
  • Child = Staff Multiselect.

The child element has a data attribute of data-departmentid.

function cascadeMultiselect(control, targetControl, key) {
         this.control = control;
         this.targetControl = targetControl;
         this.key = key;
         this.toHide = [];
         this.toShow =[];
         //Get controls selectedIds
         this.selectedIds = function() {
             var selected = [];
             _.each($(this.control + " option:selected"), function(c) {
                 selected.push($(c).val());
             });
             return selected;
         };

         //Now filter 
         this.filter = function() {

             //Get target control attribute values
             _.each($(targetControl + " option"), function(tc) {
                 //Use the val as an identifier
                 var val = $(tc).val();
                 var data = $(tc).attr("data-" + key);
                 data = data.split(",");

                 var isMatch = anyMatchInArray(data, this.selectedIds());

                 if(!isMatch){
                   $(tc).hide();
                 }
             });
         }

          this.filter();

          $(targetControl).multiselect('rebuild');           
     }

It's being called like so:

 onChange: function() {
             cascadeMultiselect('#departmentlist', '#stafflist', "DepartmentID");
         }

The problem is I can't hide the elements. The filter works just fine, I've tried:

$(tc).hide(); // tc = targetControl option

I've also tried to refresh instead of rebuild.


Solution

  • Since it seems the only way to do this was to store the values of the multiselect, and then remove / add the relevant values.

    I decided to use a rudimentary Cache class:

     var Cache = (function () {
             this.all = [];
            function Cache(control) {
                this.control = control;
             }
    
            Cache.prototype.getAll = function () {
                return this.all;
            };
    
            Cache.prototype.setAll = function (all) {
                this.all = all;
            };
            return Cache;
        })();
    

    Function now looks like:

    function cascadeMultiselect(control, targetControl, key, cache) {
             this.control = control;
             this.targetControl = targetControl;
             this.key = key;
             this.toHide = [];
             this.toShow =[];
            //To reset the multiselect
             this.reset = function(){
                 $(targetControl).html('');
                 $(targetControl).multiselect('dataprovider', cache.all)
             }
    
             //Get controls selectedIds
             this.selectedIds = function() {
                 var selected = [];
                 _.each($(this.control + " option:selected"), function(c) {
                     selected.push($(c).val());
                 });
                 return selected;
             };
    
    
             //Now filter 
             this.filter = function() {
    
                 //Get target control attribute values
                 _.each($(targetControl + " option"), function(tc) {
                     //Use the val as an identifier
                     var val = $(tc).val();
                     var data = $(tc).attr("data-" + key);
                     data = data.split(",");
    
                     var isMatch = anyMatchInArray(data, this.selectedIds());
                     console.log($(tc));
                     if(!isMatch){
                       $(tc).remove();
                     }
                 });
    
             }
             //If nothing selected then reset the multiselect
               if(this.selectedIds().length == 0){
                     this.reset();
                     return;
                 }else{
                     this.filter();
                 }
    
             $(targetControl).multiselect('rebuild');
    
         }
    

    When I first populate the multiselect with the dataprovider I add the data to the cache:

     if(cache != null){
                 cache.setAll(this.dataToAdd);
             }