AngularJS dynamic list of filters
angularjs, angularjs-filter, angularjs-ng-repeat, javascript
Solution
Without looking too much (read at all) why your attempts failed, you can achieve what you want like this:
1.) Define a list of filters and the currently selected (applied) filter in the contoller:
$scope.filters = [
{name: 'none', filterExpr: ''},
{name: 'must buy', filterExpr: {mustBuy: true}},
{name: 'promotion', filterExpr: {promotion: true}}
];
$scope.selectedFilter = $scope.filters[0];
(My filter-object have a `name` and a `filterExpr`, but you can adjust them to your needs.)
2.) Define a function for changing the applied filter (again in the contoller of course):
$scope.setFilter = function (filter) {
$scope.selectedFilter = filter;
};
3.) Let the user change the applied filter (in the view):
<ul>
<li ng-repeat="filter in filters">
<a href="" ng-click="setFilter(filter)">{{filter.name}}</a>
</li>
</ul>
4.) Filter the items, based on the currently selected filter's filter-expression:
<ul>
<li ng-repeat="item in items | filter:selectedFilter.filterExpr">
{{item.description}}
</li>
</ul>
See, also, this short demo.
Problem
I have a list of products. Each product has three properties: mustBuy, promotion (both booleans) and productName. What I'm trying to do is to apply one filter at the time, based on the user input. If the user clicks on a button called "Must buy", the products will be filtered by the mustBuy field, so once I click that button I should only see the products that have a mustBuy property with a value of true. I want to generate those filter buttons in a dynamic manner because I might add extra properties later on. Right now I have a list of hard coded buttons used for filtering: ``` <a ng-click="myFilter = {mustBuy:true}"> <img src="/images/must-filter.png" /> </a> <a ng-click="myFilter = {promotion:true}"> <img src="/images/promo-filter.png" /> </a> ``` This is what "myFilter" filters. ``` <div ng-repeat="product in products | filter:myFilter">...</div> ``` It works fine but I want to make those filters dynamic as I'll add more in the future. This is what I've tried: (v1): Js controller: ``` $scope.filters = [{ image: "must-filter.png", myFilter: { mustBuy: true } }, { image: "promo-filter.png", myFilter: { promotion: true } }]; ``` Html: ``` <a ng-repeat="f in filters | filter:f.myFilter"> <img src="/images/{{f.image}}" /> </a> ``` (v2): Js controller: ``` $scope.filters = [{ image: "must-filter.png", myFilter: { mustBuy:true } }, { image: "promo-filter.png", myFilter: {promotion:true} }]; ``` Html: ``` <a ng-repeat="f in filters" ng-click="{{f.myFilter}}"> <img src="/images/{{f.image}}" /> </a> ``` (v3): Js controller: ``` $scope.filters = [{ image: "must-filter.png", myFilter: "myFilter = {mustBuy:true}" }, { image: "promo-filter.png", myFilter: "myFilter = {promotion:true}" }]; ``` Html: ``` <a ng-repeat="f in filters" ng-click="{{f.myFilter}}"> <img src="/images/{{f.image}}" /> </a> ``` The third approach (v3) has EXACTLY the same HTML output the original (hardcoded) approach had, except it doesn't work, which makes me think there is something more (binding) happening behind the scenes? How can I achieve the functionality described in the first paragraph?