angular-bootstrap-multiselect
angular-bootstrap-multiselect copied to clipboard
reset multiselect after search
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();
};