0

I've been trying to implement filtering JS Map Object (array indexed by an id) instead of the usual js array in angularJS.

For illustration, below is a slight modification of the filtering example as provided in the AngularJS docs.

http://plnkr.co/edit/bNzePyuAAmP6Nl6hj5bI?p=preview

I have converted the input array (friends) to a JSON object with each initial array element mapped as individual keyed element. This modification can be understood below:

Initial (as shown in AngularJS docs):

friends = [{name:'John', phone:'555-1276'},
           {name:'Mary', phone:'800-BIG-MARY'},
           {name:'Mike', phone:'555-4321'},
           {name:'Adam', phone:'555-5678'},
           {name:'Julie', phone:'555-8765'}]

Modified:

friends = {1:{name:'John', phone:'555-1276'},
           2:{name:'Mary', phone:'800-BIG-MARY'},
           3:{name:'Mike', phone:'555-4321'},
           4:{name:'Adam', phone:'555-5678'},
           5:{name:'Julie', phone:'555-8765'}}

Can someone provide a way to filter such an input as part of the ng-repeat directive filter expression. I understand that 'friends' is no longer an array but an object, however since ng-repeat directive is working on this object, perhaps there is a way to filter it as well?

Thanks.

Angad
  • 3,389
  • 3
  • 30
  • 40
  • Why did you modify the original version? It is much easier to work with than the modified version. – Travis J Jun 18 '13 at 20:08
  • @TravisJ: I understand it is easier to work with the original version, given the filtering service. However, the reason I create a map instead of an array is for ease of access to each of the objects. For eg, accessing the element with name 'John' in friends array can be a lot easier in a map where all you got to do is say friends[1]. I need such easy access capability in my application. – Angad Jun 18 '13 at 20:14
  • I disagree it is easier to access the elements when it is a map. If it is an array you can use that exact same syntax, except it is zero based. – James Kleeh Jun 19 '13 at 01:52

1 Answers1

1

jsFiddle Demo - modified json structure

jsFiddle Demo - original json structure

This example maybe be very strong for your small sample, but as your sample becomes more complex this will still handle the filtering.

Use a recursive function to find the object. Originally posted by me here: https://stackoverflow.com/a/11657379/1026459

function ContainsKeyValue( obj, key, value ){
 if( obj[key] === value ) return true;
 for( all in obj )
 {
    if( obj[all] != null && obj[all][key] === value ){
        return true;
    }
    if( typeof obj[all] == "object" && obj[all]!= null ){
        var found = ContainsKeyValue( obj[all], key, value );
        if( found == true ) return true;
    }
 }
 return false;
}

You can leverage this function with or without modification of the original structure you had.

var friends = {1:{name:'John', phone:'555-1276'},
       2:{name:'Mary', phone:'800-BIG-MARY'},
       3:{name:'Mike', phone:'555-4321'},
       4:{name:'Adam', phone:'555-5678'},
       5:{name:'Julie', phone:'555-8765'}};

var filteredFriends = [];
for( var friend in friends )
{
 if( ContainsKeyValue( friends[friend], "name", "John" ) === true )
 {
    filteredFriends.push( friends[friend] );//or directly use the john object here
 }
}
console.log(filteredFriends);//this will contain an array of friends named John.
Community
  • 1
  • 1
Travis J
  • 81,153
  • 41
  • 202
  • 273
  • Thanks Travis. I can probably construct a custom filter that employs the methods provided by you and it would work out just fine. Although I was looking for something less verbose. For now what I have done is to use $scope.friends as a 'MAP' as my model and use the underscoreJS lib function _.values() on this map to bind it to another variable that holds same data as JS array. This is then used in the ng-repeat directive. What I get out of this is that I can use regular filter behavior, as well as use the MAP to easily access my model. $scope ensures that changes in MAP reflect in JS array. – Angad Jun 18 '13 at 21:31