1

Say I have an array of keys in a specific order

orderedNames=["mike","bob","sarah];

and I have a JSON that I want to show using ng-repeat but in the order that they appear in the array:

{"people":
    {
    "bob":{
        "hair":"brown",
        "eyes":"blue",
        "height":"tall"
        },
    "sarah":{
        "hair":"blonde",
        "eyes":"blue",
        "height":"short"
        }, 
    "mike":{
        "hair":"red",
        "eyes":"blue",
        "height":"tall"
        }
    }
}

How do I write a filer that would cause ng-repeat to spit out the people in the order in which they are specified in the array?

<li ng-repeat="person in people | orderNames"></li>
3
  • Why don't you want to do this in the controller? How are you getting either data (the array with the order and the other with object)? What have you tried? Commented Mar 27, 2014 at 19:47
  • I'm getting both of those things side by side from the server, the object and the array of keys. Unless there's an easy way to stuff them both into a filter, I'm probably just going to iterate over the array of ids and just get all the data directly from the model using each key rather than using ng-repeat on the object itself. Commented Mar 27, 2014 at 19:55
  • zsong answers sounds like it'd do the trick. I personally still think is better to manipulate the data on the controller as you'll have more control. zsong's answer doesn't guarantee you'll have the data displayed in the order you want. Commented Mar 27, 2014 at 20:04

4 Answers 4

4

You can define a custom filter.

Plunker: http://plnkr.co/edit/fiuuGoGZK7tM5oefKQlS

index.html

<!DOCTYPE html>
<html ng-app="plunker">

<head>
    <meta charset="utf-8" />
    <title>Filter Example</title>
    <link rel="stylesheet" href="style.css" />
    <script data-require="[email protected]" src="http://code.angularjs.org/1.2.15/angular.js" data-semver="1.2.15"></script>
    <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
<li ng-repeat="person in people|orderNames:orderedNames track by $index">{{person.hair}}</li>
</body>

</html>

app.js:

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

app.controller('MainCtrl', function($scope) {
    $scope.people={
        bob:{
            hair:"brown",
            eyes:"blue",
            height:"tall"
        },
        sarah:{
            hair:"blonde",
            eyes:"blue",
            height:"short"
        },
        mike:{
            hair:"red",
            eyes:"blue",
            height:"tall"
        }
    };
    $scope.orderedNames=["mike","bob","sarah"];

});

app.filter("orderNames",function(){
    return function(input,sortBy) {
        var ordered = [];
        for (var key in sortBy) {
            ordered.push(input[sortBy[key]]);
        }

        return ordered;
    };
});
Sign up to request clarification or add additional context in comments.

Comments

4

You could try something like this

<li ng-repeat="name in orderNames">
    {{people[name]}}
</li>

Comments

1

use array as a reference :

http://jsbin.com/jujoj/14/edit

    $scope.persons = {
   bob:{
     name:'bob'
   },
   mike:{
     name: 'mike'
   },
   sarah: {
     name: 'sarah'
   }
 };

 $scope.orderedNames = [$scope.persons.mike, $scope.persons.bob, $scope.persons.sarah];

HTML : <ul ng-repeat="person in orderedNames"> <li>{{ person.name }}</li> </ul>

Comments

0

to ng-repeat order by another array use

in the controller

$scope.somearray = [1,2,3,4] //or what ever you want to sort by

in the template.

| orderByArray:somearray:true/false

the true/false setting determines if stuff that isn't in the sortby array is outputted after the stuff that is or just dropped.

add the filter

var app = angular.module("app", []).filter("orderByArray", function () {
            return function (input, sortBy, includeOrphans) {
                //sorts by array and returns items with unsorted items at the end if they are not in the sortby array
                if (!angular.isDefined(input)) { return; }
                var ordered = [];
                var remainder = _.cloneDeep(input);
                angular.forEach(sortBy, function (sortitem) {
                    if (angular.isDefined(input[sortitem])) {
                        ordered.push(input[sortitem]);
                        delete (remainder[sortitem]);
                    }
                });
                if (includeOrphans) {
                    angular.forEach(remainder, function (remainingItem, key) {
                        ordered.push(input[key]);
                    });
                }
                return ordered;
            };
        });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.