Seen a few options for filtering data via checkboxes but it all seems fairly overly complicated for something I'd expect Angular to do easily.
Take a nose at http://plnkr.co/edit/Gog4qkLKxeH7x3EnBT0i
So there are a few filters in place here but the ones I'm interested in are the checkboxes. Using a pretty nifty Angular UI module I found called Unique, it lists the different types of providers and rather than repeating them, just lists one of each type. Lovely stuff.
However I can't get that to filter the results set below. However if I take the rendered markup from the generated checkboxes and put that directly into the HTML, it works, even though it is the same. Madness.
I don't understand filtering enough, so what am I doing wrong? I was hoping to use the unique module for a couple of other checkbox filters. Like door numbers, etc.
Here is a solution; showing diffs only:
In index.html modify the relevant lines as follows:
<li data-ng-repeat="result in results | unique: 'provider.name'">
<input type="checkbox"
id="cb_{{ result.provider.providerId }}"
data-ng-model="checkbox[result.provider.providerId]"
/>
<label for="cb_{{ result.provider.providerId }}">{{ result.provider.name }}</label>
</li>
...
<li data-ng-repeat="result in ( filteredItems = (results | filter: searchByCarClass | filter: selectCarClass | filter: searchByCheckbox )) | orderBy:orderByFilter">
...
</li>
In script.js add:
$scope.checkbox = {};
var showAll = true;
$scope.searchByCheckbox = function(result) {
return showAll || $scope.checkbox[result.provider.providerId];
};
$scope.$watch("checkbox", function(newval, oldval) {
showAll = true;
angular.forEach($scope.checkbox, function(val) {
if( val === true ) showAll = false;
});
}, true);
(EDIT) Changed the key to $scope.checkbox to providerId. Filter starts disabled, so all entries are shown.
Good luck!
Just for the fun of it, I implemented a solution that has a much simpler API (wish of Leads in comments). Here it goes:
Add the cbFilter dependency to the controller, remove all the checkbox-related code and replace it as follows; this is the new API (it can't get any simpler :)
app.controller('resultsData', function($scope, $http, cbFilter){
...
$scope.checkbox = cbFilter($scope, "provider.providerId");
...
}
Rreplace the filter in the list (notice searchByCheckbox is replaced by checkbox):
<li data-ng-repeat="result in ( filteredItems = (results | filter: searchByCarClass | filter: selectCarClass | filter: checkbox )) | orderBy:orderByFilter">
And, finally, add the service:
app.factory("cbFilter", ["$parse", function($parse) {
return function($scope, matchExpression) {
var showAll = true,
getter = $parse(matchExpression),
filter = function(data) {
if( showAll ) return true;
return filter[getter(data)] === true;
},
unwatch = $scope.$watch(
function() {
var x, ret = {};
for( x in filter ) {
if( !filter.hasOwnProperty(x) ) continue;
ret[x] = filter[x];
}
return ret;
},
function() {
showAll = true;
angular.forEach(filter, function(val) {
if( val === true ) showAll = false;
});
},
true
);
$scope.$on("$destroy", unwatch);
return filter;
};
}]);
The implementation is much more complex than before, and probably slower. However the API is much simpler (one-liner).
来源:https://stackoverflow.com/questions/18764853/angular-checkbox-filtering-data-list