Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - complex filtering based on categories etc

I've done some google-fu but all I can find about AngularJS filters is simple examples about simple filters (mostly on a single field's value).

What I'm after thoguh is somewhat more complex, and I kinda look for help on how to tackle my situation.

Imagine you have an array of the following JSON objects:

{
    "id":"1",
    "title":"Title",
    "categories":[
        {"id":"14","name":"DIY"}
    ],
    "topics":[
        {"id":"12","name":"Junk Food"}
    ]
},
{
    "id":"2",
    "title":"Title 2",
    "categories":[
        {"id":"4","name":"Test"},
        {"id":"14","name":"DIY"},
    ],
    "topics":[
        {"id":"2","name":"Food"}
    ]
}

[...]

so basically each object can have ANY number of "categories" and / or "topics".

Now, my goal is to create a frontend interface that allows me to cumulatively apply various kinds of filters to those JSON objects.

For example, I'd like to say: show only the entries that have category.id = 14 AND topic.id = 2 [etc] and still support deep-linking for the filtered results.

So here's where I'm stuck:

1) what's the best way to use routes for this (ie how would you structure the URLs to support ANY number of filter (based on different values)

2) how should i keep track of the filters added? (ie, how many and which filters have been selected by the user)

Looking at the documentation for the AngularJS filters I'll obviously use the 2nd example for the filtering parameter:

Object: A pattern object can be used to filter specific properties on objects contained by array. For example {name:"M", phone:"1"} predicate will return an array of items which have property name containing "M" and property phone containing "1". A special property name $ can be used (as in {$:"text"}) to accept a match against any property of the object. That's equivalent to the simple substring match with a string as described above.

But I'm not so sure on how to make sure i'm checking the right field (ie topic.id for topics vs category.id for categories)...

Simply put, I'd love to see an example for such a less-trivial filtering scenario.

like image 509
Pierlo Upitup Avatar asked Nov 09 '12 16:11

Pierlo Upitup


People also ask

Which one is correct way to apply filters in AngularJS?

In AngularJS, you can also inject the $filter service within the controller and can use it with the following syntax for the filter. Syntax: $filter("filter")(array, expression, compare, propertyKey) function myCtrl($scope, $filter) { $scope. finalResult = $filter("filter")( $scope.

What is the true way to apply multiple filters in AngularJS?

Answer: A is the correct option. The syntax of applying multiple filters in AngularJS can be written as: {{ expression | filter1 | filter2 | ... }}

Which character is used to chain multiple filters in AngularJS?

The pipe symbol ( | ) is used to chain multiple filters together.


2 Answers

I think you need something like this instead. See his 'other simple alternative'. I do complex filtering in a service that's injected into my controller, and expose the filtered list on my $scope to the View. I only use Angular filters for relatively simple tasks.

Re: the question about how to expose this on the URL, you'll need some way of representing those filters as strings, and can use $location and $routeParams to populate them into your controller.

like image 177
Roy Truelove Avatar answered Sep 24 '22 13:09

Roy Truelove


This can work if you write a custom filter:

var module = angular.module('app', []);

module.filter("property", ["$filter", function($filter){
    var parseString = function(input){
        return input.split(".");
    }

    function getValue(element, propertyArray) {
        var value = element;

        angular.forEach(propertyArray, function(property) {
            value = value[property];
        });

        return value;
    }

    return function (array, propertyString, target) {
        var properties = parseString(propertyString);

        return $filter('filter')(array, function(item){
            return getValue(item, properties) == target;
        });
    }
}]);

HTML part can look like this:

<ul>        
    <li ng-repeat="data in items | property:'categories.id':<id_of_a_category_we_want>">
        {{ data }}
    </li>
</ul>

Credit: OnOFF-Switch blog

like image 40
Peter Avatar answered Sep 21 '22 13:09

Peter