Logus Graphics
Logus Graphics

Reputation: 1933

AngularJS filter object by property on tree structure

I am posting this because I never found a precise answer for filtering nested objects (tree sturcture).

Let's say we have an JSON tree structure that looks like this:

$scope.tree = [{
    id: 1,
    parent_id: 0,
    name: 'Root Item',
    items: [
              {
               id: 2, 
               parent_id: 1, 
               name: '1st Child of 1'
              },
              {
               id: 3, 
               parent_id: 1, 
               name: '2nd Child of 1'
              },
              {
               id: 4, 
               parent_id: 1, 
               name: '3rd Child of 1',
               items:[
                   {
                    id:5, 
                    parent_id: 4, 
                    name:'1st Child of 5'
                    },
                   {
                    id:6, 
                    parent_id: 4, 
                    name:'2nd Child of 5'
                    }
               ]}
           ]
    }]

How do we traverse the tree with a filter to get object with id 6 for example?

Upvotes: 1

Views: 4688

Answers (1)

Logus Graphics
Logus Graphics

Reputation: 1933

If we use the following filter for example:

<div data-ng-init="selectedItem = (tree | filter:{id:6})">
  <h1>The name of item with id:6 is selectedItem.name</h1>
</div>

It will only iterate through the first level in which will only find id:1. So, in order to get nested level objects we must use a recursive filter like this one:

angular.module("myApp",[])
   .filter("filterTree",function(){
       return function(items,id){
          var filtered = [];
          var recursiveFilter = function(items,id){
              angular.forEach(items,function(item){
                 if(item.id === id){
                    filtered.push(item);
                 }
                 if(angular.isArray(item.items) && item.items.length > 0){
                    recursiveFilter(item.items,id);              
                 }
              });
          };
          recursiveFilter(items,id);
          return filtered;
       }; 
    });
});

So, to use this filter in the markup you would call it like this:

<div data-ng-init="selectedItem = (tree | filterTree:6)">
  <h1>The name of item with id:6 is selectedItem.name</h1>
</div>

Hope you find this useful, it took me some time to digest recursive filters.

Of course, this filter works to get 1 item since it returns [0] first object of filtered array. But if you want it to return more than 1 result you'll have to remove only that [0] at the return function and then use ng-repeat to iterate over filtered resutls.

Upvotes: 6

Related Questions