Reputation: 442
I have a question about how to disable a AngularJS filter related to checkboxes.
I have a classic construction:
The object:
$scope.wines = [
{ "name": "Wine a", "type": "red", "country": "france", "style": "strong" },
{ "name": "Wine a", "type": "white", "country": "italie", "style": "medium" },
{ "name": "Wine a", "type": "white", "country": "france", "style": "light" },
{ "name": "Wine a", "type": "rose", "country": "usa", "style": "strong" },
{ "name": "Wine a", "type": "champagne", "country": "chili", "style": "medium" },
{ "name": "Wine a", "type": "red", "country": "brazil", "style": "strong" },
{ "name": "Wine a", "type": "red", "country": "france", "style": "strong" }
];
$scope.winetypes = {red : true,white : true,rose : true, champagne : true};
This filter is used to display only the related choice made with the checkboxes:
app.filter('winetypefilter', function () {
return function(input, filter) {
var result = [];
angular.forEach(input, function (wine) {
angular.forEach(filter, function (isfiltered, type) {
if (isfiltered && type === wine.type) {
result.push(wine);
}
});
});
return result;
};
The results are displayed with this html code:
<li ng-repeat="(type, value) in winetypes">
<input type="checkbox" ng-model="winetypes[type]" /> {{type}}
</li>
<ul>
<li ng-repeat="wine in wines | winetypefilter:winetypes">
{{wine.name}} is a {{wine.type}} with {{wine.style}} style from {{wine.country}}
</li>
</ul>
Here the demo: http://plnkr.co/edit/nIQ2lkiJJY9MwJKHrqOk?p=preview
Upvotes: 0
Views: 2458
Reputation: 3538
http://plnkr.co/edit/w4aCjOW5UnnFQcAKYBT9?p=preview
app.filter('winetypefilter', function () {
return function(input, filter) {
var result = [];
var alt = [];
var flag = false;
angular.forEach(input, function (wine) {
flag = false;
angular.forEach(filter, function (isfiltered, type) {
if (isfiltered && type === wine.type) {
result.push(wine);
flag = true;
}
});
if(!flag)
alt.push(wine);
});
if(!angular.equals(result.length,0))
return result;
else
return alt;
};
});
As per one of the other comments, you can forgo the extra forEach
Updated Plunker: http://plnkr.co/edit/w4aCjOW5UnnFQcAKYBT9?p=preview
app.filter('winetypefilter', function () {
return function(input, filter) {
var result = [];
var alt = [];
angular.forEach(input, function (wine) {
if(filter[wine.type])
result.push(wine);
else
alt.push(wine);
});
if(!angular.equals(result.length,0))
return result;
else
return alt;
};
});
Upvotes: 1
Reputation: 30088
You can actually tweak your custom filter, winetypefilter
, to check if all winetypes
boolean values are disabled. if all values are disabled, then simply return the original array, in this case input
, otherwise continue with your original filter.
Note: I also changed the way you filtered the winetypes, the extra layer of forEach
wasn't necessary to determine if filtering should take place. just check if wine.type
of filter was true in the winetypes
json
e.g.
app.filter('winetypefilter', function () {
return function(input, filter) {
var result;
if(canFilter(filter)) {
result = [];
angular.forEach(input, function(wine) {
if(filter[wine.type])
result.push(wine);
});
} else
result = input;
return result;
};
function canFilter(filter) {
var hasFilter = false;
angular.forEach(filter, function(isFiltered) {
hasFilter = hasFilter || isFiltered;
});
return hasFilter;
}
});
Upvotes: 1
Reputation: 3462
I used ng-if
to show depending on whether all the checkboxes are checked...
<ul>
<li ng-if="check()" ng-repeat="wine in wines | winetypefilter:winetypes">
{{wine.name}} is a {{wine.type}} with {{wine.style}} style from {{wine.country}}
</li>
<li ng-if="!check()" ng-repeat="wine in wines ">
{{wine.name}} is a {{wine.type}} with {{wine.style}} style from {{wine.country}}
</li>
</ul>
and the controller code..
$scope.check=function()
{
if($scope.winetypes.red===false&&$scope.winetypes.white===false&&$scope.winetypes.rose===false&&$scope.winetypes.champagne===false)
{
return false;
}
return true;
};
http://plnkr.co/edit/MWL727Yfq8MLWodmaBDk?p=preview
Upvotes: 1