Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

reset multiselect after search #68

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open

reset multiselect after search #68

wants to merge 5 commits into from

Conversation

peppe863
Copy link

@peppe863 peppe863 commented May 8, 2018

I have fix the problem of reset multiselect after use search filter.

angular-bootstrap-multiselect.js:

(function () {
'use strict';

var multiselect = angular.module('btorfs.multiselect', ['btorfs.multiselect.templates']);

multiselect.getRecursiveProperty = function (object, path) {
    return path.split('.').reduce(function (object, x) {
        if (object) {
            return object[x];
        } else {
            return null;
        }
    }, object)
};

multiselect.directive('multiselect', ['$filter', '$document', '$log', function ($filter, $document, $log) {
    return {
        restrict: 'AE',
        scope: {
            options: '=',
            displayProp: '@',
            idProp: '@',
            searchLimit: '=?',
            selectionLimit: '=?',
            showSelectAll: '=?',
            showUnselectAll: '=?',
            showSearch: '=?',
            searchFilter: '=?',
            disabled: '=?ngDisabled',
            labels: '=?',
            classesBtn: '=?',
            showTooltip: '=?',
            placeholder: '@?',
            opt: '=' 
        },
        require: 'ngModel',
        templateUrl: 'multiselect.html',
        controller: ['$scope', function($scope) {
            if (angular.isUndefined($scope.classesBtn)) {
                $scope.classesBtn = ['btn-block','btn-default'];
            }
        }],
        link: function ($scope, $element, $attrs, $ngModelCtrl) {
            $scope.selectionLimit = $scope.selectionLimit || 0;
            $scope.searchLimit = $scope.searchLimit || 25;

            $scope.searchFilter = '';

            $scope.resolvedOptions = [];
            if (typeof $scope.options !== 'function') {
                $scope.resolvedOptions = $scope.options;
            }

            if (typeof $attrs.disabled != 'undefined') {
                $scope.disabled = true;
            }


            var closeHandler = function (event) {
                if (!$element[0].contains(event.target)) {
                    $scope.$apply(function () {
                        $scope.open = false;
                    });
                }
            };

            $document.on('click', closeHandler);

            var updateSelectionLists = function () {
                if (!$ngModelCtrl.$viewValue) {
                    if ($scope.selectedOptions) {
                        $scope.selectedOptions = [];
                    }
                    $scope.unselectedOptions = $scope.resolvedOptions.slice(); // Take a copy
                } else {
                    $scope.selectedOptions = $scope.resolvedOptions.filter(function (el) {
                        var id = $scope.getId(el);
                        for (var i = 0; i < $ngModelCtrl.$viewValue.length; i++) {
                            var selectedId = $scope.getId($ngModelCtrl.$viewValue[i]);
                            if (id === selectedId) {
                                return true;
                            }
                        }
                        return false;
                    });
                    $scope.unselectedOptions = $scope.resolvedOptions.filter(function (el) {
                        return $scope.selectedOptions.indexOf(el) < 0;
                    });
                }
            };

            $scope.toggleDropdown = function () {
                $scope.open = !$scope.open;
                $scope.resolvedOptions = $scope.options;
                updateSelectionLists();
            };

            $ngModelCtrl.$render = function () {
                updateSelectionLists();
            };

            $ngModelCtrl.$viewChangeListeners.push(function () {
                updateSelectionLists();
            });

            $ngModelCtrl.$isEmpty = function (value) {
                if (value) {
                    return (value.length === 0);
                } else {
                    return true;
                }
            };

            var watcher = $scope.$watch('selectedOptions', function () {
                $ngModelCtrl.$setViewValue(angular.copy($scope.selectedOptions));
            }, true);

            $scope.$on('$destroy', function () {
                $document.off('click', closeHandler);
                if (watcher) {
                    watcher(); // Clean watcher
                }
            });

            $scope.getButtonText = function () {
                if ($scope.selectedOptions && $scope.selectedOptions.length === 1) {
                    return $scope.getDisplay($scope.selectedOptions[0]);
                }
                if ($scope.selectedOptions && $scope.selectedOptions.length > 1) {
                    var totalSelected = angular.isDefined($scope.selectedOptions) ? $scope.selectedOptions.length : 0;
                    if (totalSelected === 0) {
                        return $scope.labels && $scope.labels.select ? $scope.labels.select : ($scope.placeholder || 'Select');
                    } else {
                        return totalSelected + ' ' + ($scope.labels && $scope.labels.itemsSelected ? $scope.labels.itemsSelected : 'selected');
                    }
                } else {
                    return $scope.labels && $scope.labels.select ? $scope.labels.select : ($scope.placeholder || 'Select');
                }
            };

            $scope.selectAll = function () {
                $scope.selectedOptions = $scope.resolvedOptions.slice(); // Take a copy;
                $scope.unselectedOptions = [];
            };

            $scope.unselectAll = function () {
                $scope.selectedOptions = [];
                $scope.unselectedOptions = $scope.resolvedOptions.slice(); // Take a copy;
            };

            $scope.toggleItem = function (item) {
                if (typeof $scope.selectedOptions === 'undefined') {
                    $scope.selectedOptions = [];
                }
                var selectedIndex = $scope.selectedOptions.indexOf(item);
                var currentlySelected = (selectedIndex !== -1);
                if (currentlySelected) {
                    $scope.unselectedOptions.push($scope.selectedOptions[selectedIndex]);
                    $scope.selectedOptions.splice(selectedIndex, 1);
                } else if (!currentlySelected && ($scope.selectionLimit === 0 || $scope.selectedOptions.length < $scope.selectionLimit)) {
                    var unselectedIndex = $scope.unselectedOptions.indexOf(item);
                    $scope.unselectedOptions.splice(unselectedIndex, 1);
                    $scope.selectedOptions.push(item);
                }
            };

            $scope.getId = function (item) {
                if (angular.isString(item)) {
                    return item;
                } else if (angular.isObject(item)) {
                    if ($scope.idProp) {
                        return multiselect.getRecursiveProperty(item, $scope.idProp);
                    } else {
                        $log.error('Multiselect: when using objects as model, a idProp value is mandatory.');
                        return '';
                    }
                } else {
                    return item;
                }
            };

            $scope.getDisplay = function (item) {
                if (angular.isString(item)) {
                    return item;
                } else if (angular.isObject(item)) {
                    if ($scope.displayProp) {
                        return multiselect.getRecursiveProperty(item, $scope.displayProp);
                    } else {
                        $log.error('Multiselect: when using objects as model, a displayProp value is mandatory.');
                        return '';
                    }
                } else {
                    return item;
                }
            };

            $scope.isSelected = function (item) {
                if (!$scope.selectedOptions) {
                    return false;
                }
                var itemId = $scope.getId(item);
                for (var i = 0; i < $scope.selectedOptions.length; i++) {
                    var selectedElement = $scope.selectedOptions[i];
                    if ($scope.getId(selectedElement) === itemId) {
                        return true;
                    }
                }
                return false;
            };

            $scope.updateOptions = function () {
                if (typeof $scope.options === 'function') {
                    $scope.options().then(function (resolvedOptions) {
                        $scope.resolvedOptions = resolvedOptions;
                        updateSelectionLists();
                    });
                }
            };
            
            angular.extend($scope.opt, {
              directiveFunction: function() {
            	  $scope.searchFilter = '';
            	  $scope.search();
              }
            });

            // This search function is optimized to take into account the search limit.
            // Using angular limitTo filter is not efficient for big lists, because it still runs the search for
            // all elements, even if the limit is reached
            $scope.search = function () {
                var counter = 0;
                return function (item) {
                    if (counter > $scope.searchLimit) {
                        return false;
                    }
                    var displayName = $scope.getDisplay(item);
                    if (displayName) {
                        var result = displayName.toLowerCase().indexOf($scope.searchFilter.toLowerCase()) > -1;
                        if (result) {
                            counter++;
                        }
                        return result;
                    }
                }
            };

        }
    };
}]);

}());

angular.module('btorfs.multiselect.templates', ['multiselect.html']);

angular.module("multiselect.html", []).run(["$templateCache", function ($templateCache) {
$templateCache.put("multiselect.html",
"<div class="btn-group" style="width: 100%">\n" +
" <button type="button" class="btn dropdown-toggle" ng-class="classesBtn" ng-click="toggleDropdown()" ng-disabled="disabled" style="white-space: nowrap; overflow-x: hidden; text-overflow: ellipsis;">\n" +
" {{getButtonText()}} <span class="caret">\n" +
" \n" +
" <ul class="dropdown-menu dropdown-menu-form dropdown-menu-form-custom"\n" +
" ng-style="{display: open ? 'block' : 'none'}" style="width: 100%; overflow-x: auto">\n" +
"\n" +
" <li ng-show="showSelectAll">\n" +
" <a ng-click="selectAll()" href="">\n" +
" <span class="glyphicon glyphicon-ok"> {{labels.selectAll || 'Select All'}}\n" +
" \n" +
" \n" +
" <li ng-show="showUnselectAll">\n" +
" <a ng-click="unselectAll()" href="">\n" +
" <span class="glyphicon glyphicon-remove"> {{labels.unselectAll || 'Unselect All'}}\n" +
" \n" +
" \n" +
" <li ng-show="(showSelectAll || showUnselectAll)"\n" +
" class="divider">\n" +
" \n" +
"\n" +
" <li role="presentation" ng-repeat="option in selectedOptions" class="active">\n" +
" <a class="item-selected" href="" title="{{showTooltip ? getDisplay(option) : ''}}" ng-click="toggleItem(option); $event.stopPropagation()" style="overflow-x: hidden;text-overflow: ellipsis">\n" +
" <span class="glyphicon glyphicon-remove">\n" +
" {{getDisplay(option)}}\n" +
" \n" +
" \n" +
" <li ng-show="selectedOptions.length > 0" class="divider">\n" +
"\n" +
" <li ng-show="showSearch">\n" +
" <div class="dropdown-header">\n" +
" <input type="text" class="form-control input-sm" style="width: 100%;"\n" +
" ng-model="searchFilter" placeholder="{{labels.search || 'Search...'}}" ng-change="updateOptions()"/>\n" +
" \n" +
" \n" +
"\n" +
" <li ng-show="showSearch" class="divider">\n" +
" <li role="presentation" ng-repeat="option in unselectedOptions | filter:search() | limitTo: searchLimit"\n" +
" ng-if="!isSelected(option)"\n" +
" ng-class="{disabled : selectionLimit && selectedOptions.length >= selectionLimit}">\n" +
" <a class="item-unselected" href="" title="{{showTooltip ? getDisplay(option) : ''}}" ng-click="toggleItem(option); $event.stopPropagation()" style="overflow-x: hidden;text-overflow: ellipsis">\n" +
" {{getDisplay(option)}}\n" +
" \n" +
" \n" +
"\n" +
" <li class="divider" ng-show="selectionLimit > 1">\n" +
" <li role="presentation" ng-show="selectionLimit > 1">\n" +
" {{selectedOptions.length || 0}} / {{selectionLimit}} {{labels.itemsSelected || 'selected'}}\n" +
" \n" +
"\n" +
" \n" +
"\n" +
"");
}]);

HTML EXAMPLE:

CALL RESET FROM CONTROLLER:

	$scope.dirOptComuni = {};
	$scope.callDirFunc = function(){
		$scope.dirOptComuni.directiveFunction();
	};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant