I have an ng-repeat list with multiple filters, but as I need the elements to be hidden and not removed from the DOM, I use ng-show for the filtering.
This is how my first filter look like:
<a href="" ng-click="myFilter = ''; toggle = toggle=0; togglesec=0; mySecondFilter = {}" ng-class="{'active' : toggle==0}" >
Tot
</a>
<a href="" ng-click="myFilter = 'pa'; toggle = toggle=1; togglesec=0; mySecondFilter = {}" ng-class="{'active' : toggle==1}">
Pa
</a>
<a href="" ng-click="myFilter = 'Reposteria'; toggle = toggle=2; togglesec=0; mySecondFilter = {}" ng-class="{'active' : toggle==2}">
Reposteria
</a>
And the second one:
<div ng-init="togglesec=0; mySecondFilter = {}">
<a ng-click="mySecondFilter = {}; togglesec = togglesec=0" ng-class="{'active' : togglesec==0}">
All
</a>
<a ng-click="mySecondFilter = {'vegan': true}; togglesec = togglesec=1" ng-class="{'active' : togglesec==1}">
Vegan
</a>
<a ng-click="mySecondFilter = {'gluten': true}; togglesec = togglesec=2" ng-class="{'active' : togglesec==2}">
Gluten Free
</a>
</div>
Now, I was able to filter the ng-repeat using ng-show and the first filter like so:
<div ng-repeat="pa in products" ng-show="pa.tipus.indexOf(myFilter) != -1">
Basically it compares the value of myFilter with the pa.tipus object property, and it works OK.
But it won't work with the second filter, because mySecondFilter is an object, not a string (it needs to filter the results containing vegan:true or gluten:true)
Here's an example of my object type:
pa {
tipus : 'pa',
gluten : false,
vegan : true
}
Any tips on how to combine both filters in the same ng-show?
I've applied the answer by Naren, but I get the following error on click on any filter:
angular.min.js:122 TypeError: Cannot create property 'vegan' on string ''.
I've also tried to initialize myFilter by adding this, but no luck, same error appears:
$scope.myFilter = {
tipus : '',
vegan : '',
gluten : '',
lactosa : ''
};
Update:
Since the user wanted a generic version for the filtering. The following function should be the answer.
$scope.validate = function(row) {
for (var key in $scope.myFilter) {
if ($filter('filter')([row], {
[key]: $scope.myFilter[key]
}).length === 0) {
return false;
}
}
return true;
}
Where we loop through an object where all the filters are stored, then return false if any of the filters are not satisfied.
Please check the below example to get a understanding of how the filter works.
Old:
Here is my version of the fix. Angular's $filter
will be great for identifying the object with the property, but this is not possible to have written in the HTML, hence I call a function which will return true or false to the ng-show
.
$scope.validate = function(row) {
if (row.tipus.indexOf($scope.myFilter) != -1) {
if ($filter('filter')([row], $scope.mySecondFilter).length !== 0) {
return true;
} else {
return false;
}
} else {
return false;
}
}
Let me explain the function. First we receive the row of the ng-repeat
through the parameter of validate, after which I apply the first if
condition which is basically whatever you had written earlier, this code works great btw. Then I check the row using the $filter
syntax for the object present in $scope.mySecondFilter
, Refer here for more on filtering with $filter
, this will basically check if the row passed contains the required object property and return true
or false
.
Here is a working example of your code for reference.
Please let me know if this fixes your issue completely :)