0

I am using the angular advanced search box and I want to implement a custom filter in my angular page but I am having trouble figuring out how to handle a string of requirements in a query. Let's say I have several objects that follow the following format:

{
    "displayName":"John",
    "gender":"male",
    "type":"customer",
    "items": 3,
}

I would want to be able to search in plain english `Anyone who's name is John and is of type Customer". Here is my angular search code so far:

app.filter('infoFilter', function() {
    return function(data, query) {
        var output = [];
        var index;

        //loop over the original array
        angular.forEach(data, function(row, index) {
            angular.forEach(query, function(input, value) {
                if(input) {
                    if(angular.isNumber(row[value]) && row[value] == input) {
                        output.push(row);
                    } else if(!angular.isNumber(row[value]) && row[value].toLowerCase().indexOf(input.toLowerCase()) > -1) {
                        output.push(row);
                    }
                }
            });
        });
        if(query) {
            return data;
        } else {
            return output;
        }
    }
});

The query comes in as an object that looks like this:

{
    "displayName":"John"
}

This works perfectly fine for 1 search parameter. So if I searched for John my table would update to show all entries with the name of john. However, this wouldn't really work for multi search parameters. So if the query looked like this:

{
    "displayName":"John",
    "gender":"Female"
}

I need to apply all the parameters at once before i do output.push(row). How exactly would I go about doing this?

1
  • those multiple parameter should work in what way AND/OR condition..? single record should match both query, or any record will have one of them. Commented Apr 20, 2016 at 21:53

1 Answer 1

3

If I understand you correctly you want to filter the rows where all query parameters apply (AND). I modified your code slightly to achieve this behavior.

app.filter('infoFilter', function() {
    return function(data, query) {
        var output = [];
        var index;

        //loop over the original array
        angular.forEach(data, function(row, index) {

            var pushRow = true;

            angular.forEach(query, function(input, value) {
                if(input) {
                    if(angular.isNumber(row[value]) && row[value] == input) {
                        return;
                    } else if(!angular.isNumber(row[value]) && row[value].toLowerCase().indexOf(input.toLowerCase()) > -1) {
                        return;
                    }
                }
                pushRow = false;
            });

            if (pushRow) {
                output.push(row);
            }
        });

        // This bit also seems to be the wrong way around in your code.
        if(!query) {
            return data;
        } else {
            return output;
        }
    }
});

Edit:

Here is also an optimized version of the same filter using javascripts built in array functions.

app.filter('infoFilter', function() {
    return function(data, query) {
        if(!query || !data) {
            return data;
        }

        return data.filter(function(row) {
            return Object.keys(query).every(function(key) {
                var rowValue = row[key];
                var queryValue = query[key];

                return (angular.isNumber(rowValue) && rowValue == input) ||
                        (angular.isString(rowValue) && rowValue.toLowerCase().indexOf(queryValue.toLowerCase()) > -1);
            });
        });
    };
});
Sign up to request clarification or add additional context in comments.

3 Comments

this is perfect but for some reason I keep getting the error TypeError: Cannot read property 'filter' of undefined. Any idea what that is about?
Probably because data is undefined.
yep, that was it. Thank you! I have a question about how to extract operators but I'll make a new post about that.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.