I am new to AngularJS and I'm having problems doing a reusable generic filter.
Let's say I have a colors, types, and list objects as seen below (New JSON). I want to make a generic filter that will take colors and types objects and filter the list object without having to use the string match as filter.
For now I did specific filters by strings as seen below.
I will have a lot of information in these objects and I don't want to update the controller each time a new property is being included in the JSON.
How do I associate the number to its specific string value?
[
{
"id": 1,
"name": "Spike",
"type": "dog",
"color": "gray"
},
{
"id": 2,
"name": "Tom",
"type": "cat",
"color": "blue"
},
{
"id": 3,
"name": "Butch",
"type": "cat",
"color": "black"
}
]
// colors
[
{"gray": 1},
{"black": 2},
{"blue": 3},
]
// types
[
{"dog": 1},
{"cat": 2}
]
// data list
[
{
"id": 1,
"type": 1,
"name": "Spike",
"color": 1
},
{
"id": 2,
"type": 2,
"name": "Tom",
"color": 3
},
{
"id": 3,
"type": 2,
"name": "Butch",
"color": 2
}
]
<table class="table table-bordered table-condensed table-striped table-hover">
<thead>
<tr>
<th>
<a>
Filters:
</a>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="item in typeItems">
<td>
<label class="check">
<input type="checkbox" ng-model="typeFilterItems[item.type]">{{item.type}}
</label>
</td>
</tr>
<tr ng-repeat="item in colorItems">
<td>
<label class="check">
<input type="checkbox" ng-model="colorFilterItems[item.color]">{{item.color}
</label>
</td>
</tr>
</tbody>
</table>
<table class="table table-bordered table-condensed table-striped table-hover header-fixed">
<thead>
<tr>
<th>ID</th>
<th>Type</th>
<th>Color</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr class="list" ng-repeat="item in animals | filter:typeFilter | filter:colorFilter">
<td>{{item.id}</td>
<td>{{item.type}}</td>
<td>{{item.color}}</td>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
Controller
Animals.list().then(function (data) {
$scope.animals = data;
});
$scope.colorFilterItems = { 'black': true, 'gray': false, 'blue': false }; // doing this to have a predefined filter selection ... for now
$scope.colorItems = [{ name: 'black' }, { name: 'gray' }, { name: 'blue' }];
$scope.colorFilter = function (item) {
return $scope.colorFilterItems[item.color]
};
$scope.typeFilterItems = { 'dog': true, 'cat': false }; // doing this to have a predefined filter selection ... for now
$scope.typeItems = [{ name: 'black' }, { name: 'gray' }, { name: 'blue' }];
$scope.typeFilter = function (item) {
return $scope.typeFilterItems[item.type]
};
Since no one answered I eventually found a solution.
The answer to all this is to use lodash directly inside the service and create a filter method inside the promise that looks for the selected property inside the filter objects and compares them to the data we want to display.
filterAnimals = () => {
intersectedResults =
_.filter(animals,(animal: iAnimal) => {
var colors = _.find(colorLabels,(item: iFilter) => {
return (animal.color ? item.label === animal.color : item.label == null) && item.selected;
});
var types = _.find(typeLabels,(item: iFilter) => {
return (animal.type ? item.label === animal.type : item.label == null) && item.selected;
});
return colors && types;
});
return data;
};
After doing this I acces the filterAnimals() function from the controller and bind the checkbox filters to my data. When doing an ng-change on the checkbox this function executes and checks the filters against the data and it shows the data I need.