Solution
Sergio's answer below worked great, specifically the objectsMatch function he provided. I also need to support multi-select select elements for filtering so I modified his function a bit, here it is in case anyone else is looking for similar functionality:
function objectsMatch(roll, filterObject) {
var match = true;
for (var prop in filterObject) {
if(!roll.hasOwnProperty(prop) ||
!filterObject.hasOwnProperty(prop)) continue;
if(Array.isArray(filterObject[prop])){
var matchesNoValues = function(){
for(var i = 0; i < filterObject[prop].length; i++){
console.log(filterObject[prop][i])
if(roll[prop] == filterObject[prop][i]){
return false;
}
}
return true;
}
if (matchesNoValues() &&
filterObject[prop] != ''
) {
match = false;
}
}else{
if (roll[prop] != filterObject[prop] &&
filterObject[prop] != ''
) {
match = false;
}
}
}
return match;
}
EDIT 1
I was able to replicate the functionality I'm looking for in an MVP here. And am now trying to figure out how to apply that to my filter. Hopefully this can better demonstrate what I'm trying to achieve.
Original Post
I am attempting to add a custom filter for filtering rows in a table in Angular. I need to check whether each object in my repeat has all the values represented in my filters array. These values are set by select elements in my table.
For example, my data set looks like:
$scope.sushi = [
{ name: 'Cali Roll', fish: 'Crab', tastiness: 2 },
{ name: 'Philly', fish: 'Tuna', tastiness: 4 },
{ name: 'Tiger', fish: 'Eel', tastiness: 7 },
{ name: 'Tiger', fish: 'Tuna', tastiness: 3 },
{ name: 'Rainbow', fish: 'Variety', tastiness: 62 }
];
And say my filters array contains:
var filters = ['Philly', 'Tuna', 4];
it will only show
$scope.sushi[1]
in the repeat.
Then say the filters array values are updated to:
var filters = ['Philly', 'Tuna', 1000];
Now no rows would display because there is no object in my dataset that contains all the values in the filters array.
HERE is a link to what I've tried so far, with both methods marked METHOD 1 and METHOD 2, respectively.
I think I'm almost there with METHOD 1, but if I select multiple values that are in the object, no rows get displayed, it only displays a row when I only select 1 filter. As for METHOD 2, its only checking that at least one of the values in the filters array are in the object, not all.
Here is the full code in my filter:
.filter('byColumn', function(){
return function(rolls, filterVal){
var filtered = [];
var test = true;
for(var x in rolls){
var currentRoll = rolls[x];
for(y in currentRoll){
// METHOD 1
var allMatches = true;
for(var i = 0; i < filterVal.length; i++){
if(filterVal[i]){
if(currentRoll[y] == filterVal[i]){
continue;
}else{
allMatches = false;
break;
}
}
}
if(allMatches){
if (filtered.indexOf(currentRoll) == -1) {
filtered.push(currentRoll);
}
}
if(!allMatches){
rolls = [];
}
// METHOD 2
// angular.forEach(filterVal, function(filter){
// if(currentRoll[y] == filter){
// if (filtered.indexOf(currentRoll) == -1) {
// filtered.push(currentRoll);
// }
// }
// });
}
}
return filtered.length ? filtered : rolls;
}
});
The code is based off a tutorial by Scotch.io found here that I have modified to fit my needs.
Thanks in advance for any suggestions.