angularjs-dropdown-multiselect
angularjs-dropdown-multiselect copied to clipboard
Check All function selects disabled items
There is an issue with the Check All / Select All function.
$scope.selectAll = function() {
var searchResult;
$scope.deselectAll(true);
$scope.externalEvents.onSelectAll();
searchResult = $filter('filter')($scope.options, $scope.getFilter($scope.input.searchFilter));
angular.forEach(searchResult, function(value) {
$scope.setSelectedItem(value[$scope.settings.idProp], true, false);
});
$scope.externalEvents.onSelectionChanged();
$scope.selectedGroup = null;
};
When you disable an item, the select all does not have a check | filter to see if an item has been disabled.
Also, to note, the disabled item doesn't look disabled.
I ran into the same issue. It looks like no-one's maintaining the project any longer, so this is how I fixed it:
- Moved the .onSelectAll() call to after the default processing in the
$scope.selectAllfunction. (see below) - Added a custom onSelectAll handler within my app controller which will unselect any disabled items. (not shown here)
- Added the below CSS to my application's stylesheet for visually noting the disabled options. (see below)
Modified onSelectAll()
$scope.selectAll = function() {
var searchResult;
$scope.deselectAll(true);
searchResult = $filter('filter')($scope.options, $scope.getFilter($scope.input.searchFilter));
angular.forEach(searchResult, function(value) {
$scope.setSelectedItem(value[$scope.settings.idProp], true, false);
});
$scope.externalEvents.onSelectAll();
$scope.externalEvents.onSelectionChanged();
$scope.selectedGroup = null;
};
CSS Styling
/* make hover background same as the normal background for disabled */
.dropdown-menu li > a[disabled].option:hover {
background-color: white;
background-image: none;
}
/* make option text light grey for disabled */
.dropdown-menu a[disabled].option {
color: #b3b1b1;
}
I solved this issue also by modifying the original code.
The main idea was to make it so the "Deselect All" removes all but currently disabled (and selected) options, via the selectedModel.
Then, the "Select All" will also only select options that are NOT disabled. (deselectAll is called from selectAll, so it's important for Deselect All to be handled correctly)
Modified $scope.selectAll
$scope.selectAll = function() {
var searchResult;
var filteredResult;
$scope.deselectAll(true);
$scope.externalEvents.onSelectAll();
searchResult = $filter('filter')($scope.options, $scope.getFilter($scope.input.searchFilter));
filteredResult = searchResult.filter(function (option) {
return !option.disabled;
});
angular.forEach(filteredResult, function(value) {
$scope.setSelectedItem(value[$scope.settings.idProp], true, false);
});
$scope.externalEvents.onSelectionChanged();
$scope.selectedGroup = null;
};
Modified $scope.deselectAll
$scope.deselectAll = function(dontSendEvent) {
dontSendEvent = dontSendEvent || false;
if (!dontSendEvent) {
$scope.externalEvents.onDeselectAll();
}
if ($scope.singleSelection) {
if (!$scope.selectedModel.disabled) {
clearObject($scope.selectedModel);
}
} else {
$scope.selectedModel = $scope.filterDisabledSelection($scope.selectedModel, $scope.options);
}
if (!dontSendEvent) {
$scope.externalEvents.onSelectionChanged();
}
$scope.selectedGroup = null;
};
"Deselect All" references this newly added function:
Note: This uses the lodash _.find function doc here. You'll need to refactor this if you don't have lodash.
$scope.filterDisabledSelection = function (array, options) {
return array.filter(function (option) {
var id;
if ($scope.settings.externalIdProp === '') {
id = option[$scope.settings.idProp];
} else {
id = option[$scope.settings.externalIdProp];
}
var match = _.find(options, [$scope.settings.idProp, id]);
return match && match.disabled;
});
};
Bonus:
From a styling point, I made sure that the list items receive the disabled class correctly for the templating:
if (groups) {
template += '<li ng-repeat-start="option in orderedItems | filter:getFilter(input.searchFilter)" ng-show="getPropertyForObject(option, settings.groupBy) !== getPropertyForObject(orderedItems[$index - 1], settings.groupBy)" role="presentation" class="dropdown-header">{{ getGroupLabel(getPropertyForObject(option, settings.groupBy)) }}</li>';
template += '<li ng-class="{\'active\': isChecked(getPropertyForObject(option,settings.idProp)) && settings.styleActive && !option.disabled, \'disabled\': option.disabled}" ng-repeat-end role="presentation">';
} else {
template += '<li ng-class="{\'active\': isChecked(getPropertyForObject(option,settings.idProp)) && settings.styleActive && !option.disabled, \'disabled\': option.disabled}" role="presentation" ng-repeat="option in options | filter:getFilter(input.searchFilter)">';
}