panzhuli
panzhuli

Reputation: 2940

Angular filter json object

I'm trying to implement a filter based on the answer to this question, but it isn't working for me. For code:

function MyCtrl($scope, $timeout)
{
    $scope.tweets = [
        {
            created_at: "Date",
            text: "tweet text",
            users: 
            [
                {
                    name: "user name",
                    screen_name: "user screen name",
                    profile_image_url: "profile pic"
                },
                {
                    name: "user name 2",
                    screen_name: "user screen name 2",
                    profile_image_url: "profile pic"
                }
            ]
        },
        {
            created_at: "Date",
            text: "tweet text 2",
            users: 
            [
                {
                    name: "user name",
                    screen_name: "user screen name",
                    profile_image_url: "profile pic"
                },
                {
                    name: "user name 2",
                    screen_name: "user screen name 2",
                    profile_image_url: "profile pic"
                }
            ]
        },
        {
            created_at: "Date",
            text: "tweet text 3",
            users: 
            [
                {
                    name: "user name",
                    screen_name: "user screen name",
                    profile_image_url: "profile pic"
                },
                {
                    name: "user name 2",
                    screen_name: "user screen name 2",
                    profile_image_url: "profile pic"
                }
            ]
        }
    ];
}

and the template:

<div ng-app ng-controller="MyCtrl">
    <div ng-repeat="tweet in tweets">
        for each tweet, user 2's name should be printed here >>
        {{(tweet.users | filter:{screen_name:'user screen name 2'}).name}}
        _____________________________________
    </div>

</div>

I'm seeing output of:

for each tweet, user 2's name should be printed here >>


for each tweet, user 2's name should be printed here >>


for each tweet, user 2's name should be printed here >>


I would expect that "user name 2" would be printed out after each ">>". I don't know why that filter isn't working on an array of each iterated element. Thanks.

fiddle

Upvotes: 0

Views: 2731

Answers (3)

Gajender Singh
Gajender Singh

Reputation: 1313

Query is your string and filter my query like name present in json list
ng-repeat="tweet in tweets" | filter: { users: query }

Upvotes: 0

Rodmentou
Rodmentou

Reputation: 1640

AND IF THE SAME USER IS MORE THAN ONCE ON THE SAME MESSAGE?

If you have more than one message from one user, the above answer will not work and, instead, will display something strange.

In order to better filter your data, you should try to use filter functions when you have nested objects or arrays inside objects and arrays. I had a similar problem in this question: Filtering data with AngularJS Filter. How to iterate over objects?

So, to your question!

First, you need to go one level above to apply the filter to all the objects. Using the filter where you are, you can't see the big picture and act according. The tack by is being used because ng-repeat can't have duplicated values in a array.

<div ng-app='app' ng-controller="MyCtrl">
    <div ng-repeat="tweet in tweets | custom track by $index">
        for each tweet, user 2's name should be printed here >>
        {{  tweet }}
        _____________________________________
    </div>
</div>

Now, this is the important part. I'm registering a angular.module as app just because I prefer this way. After that, I create a filter called custom that was acessed in the html code.

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

I've changed a little your code, So I can see it better in my way:

app.controller('MyCtrl', function ($scope, $timeout){...});

app.filter('custom', function () {
    return function (tweets) {
        var formatted = []; //Initialize array to be returned.
        for (var j = 0; j < tweets.length; j++) { //Iterate over all tweets.
            var tweet = tweets[j]; //Select a single tweet.
            //Above, iterate over all users on a tweet.
            for (var i = 0; i < tweet.users.length; i++) {
                var user = tweet.users[i]; //Select a single user of the tweet.
                if (tweet.user[i].screen_name == 'user screen name 2'){
                    //If match what you want, insert it in the array to be returned.
                    formatted.push(tweet.user[i].name);
                };
            };        
        };
        return formatted; //Return the array.
    };
});

And, finally, if you want to test, here are a fully function jsfiddle with your own code. :)

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 692151

The filter doesn't return a user. It returns an array of users matching the filter condition. So in that case, an array containing one user.

So it should be

{{(tweet.users | filter:{screen_name:'user screen name 2'})[0].name}}

You could have found this yourself easily by just using

{{ (tweet.users | filter:{screen_name:'user screen name 2'}) }}

to see what the result of the filter was.

Upvotes: 2

Related Questions