161

I'm populating a dropdown through the use of ng-options which is hooked to a controller that in turn is calling a service. Unfortunately the data coming in is a mess and I need to be able to sort it alphabetically.

You figure that something like $.sortBy would do it but unfortunately it didn't do jack. I know I can sort it via javascript with a helper method function asc(a,b) or something like that but I refuse to believe that there is not cleaner way of doing this plus I don't want to bloat the controller with helper methods. It is something so basic in principle so I don't understand why AngularJS doesn't have this.

Is there a way of doing something like $orderBy('asc')?

Example:

<select ng-option="items in item.$orderBy('asc')"></select>

It would be extremely useful to have options in orderBy so you can do whatever you want, whenever you usually try to sort data.

Eliran Malka
  • 15,821
  • 6
  • 77
  • 100
J Castillo
  • 3,357
  • 5
  • 27
  • 28

4 Answers4

344

Angular has an orderBy filter that can be used like this:

<select ng-model="selected" ng-options="f.name for f in friends | orderBy:'name'"></select>

See this fiddle for an example.

It's worth noting that if track by is being used it needs to appear after the orderBy filter, like this:

<select ng-model="selected" ng-options="f.name for f in friends | orderBy:'name' track by f.id"></select>
Rahul Desai
  • 15,242
  • 19
  • 83
  • 138
Gloopy
  • 37,767
  • 15
  • 103
  • 71
  • 1
    Looking at the fiddle (or adding a sort select tag to the Angular ToDo tutorial), getting an option to show as 'selected' - or even getting the first option to show - is an issue. With Angular it's blank? – Dave Everitt Apr 07 '13 at 16:52
  • 2
    @DaveEveritt one way to set a default (and to remove the blank item) is to pre-select a bound item for `selected`. For this example you can do something like `$scope.selected = $scope.friends[0]`. See [this fiddle](http://jsfiddle.net/aBccw/142/) for a working sample. – Gloopy Apr 08 '13 at 05:19
  • what if I want age as value in selected, not the whole JSON element? – Rishi Mar 02 '15 at 12:57
  • @Rishi try this for ng-options: `f.age as f.name for f in friends | orderBy:'name'` - [here](http://jsfiddle.net/aBccw/588/) is a working fiddle. More on ng-options [here](https://docs.angularjs.org/api/ng/directive/ngOptions). – Gloopy Mar 02 '15 at 17:36
  • @VladimirStarkov you're wrapping the orderBy parameter in quotes because angular will use it as a primitive _value_ to specify the key in your friend object. It will be used by angular to dynamically specify the key of the property in your object that you're wanting to order by: `friend['name']`. If you tried to do `friend[name]`, (no quotes), `name` will get treated like a variable; and if `name` is undefined, you'll get an exception. – Danny Bullis May 05 '15 at 21:01
  • what about ordering (key, value) by value? – Atav32 Aug 21 '15 at 00:57
  • 7
    @Gloopy, This answer got me 90% of the way there. Would you mind adding a case for when track by is used? ` – MushinNoShin Aug 27 '15 at 14:01
  • @MushinNoShin I actually have never used `track by` but I can see if I upgrade the fiddle to 1.2 ([see here](http://jsfiddle.net/aBccw/852/)) the following syntax doesn't throw a js error: `ng-options="f.name for f in friends track by f.id | orderBy:'name'"` – Gloopy Aug 27 '15 at 16:39
  • @Gloopy If you look at the dropdown values in the fiddle you'll notice they aren't sorted. – MushinNoShin Aug 27 '15 at 23:18
  • @MushinNoShin might be missing something but moved the options back to how you had it originally and it [appears to work](http://jsfiddle.net/aBccw/853/). – Gloopy Aug 28 '15 at 00:06
  • @Gloopy yes, in [your original](http://jsfiddle.net/aBccw/852/) the sorting is broken. John appears before Adam. In [your new fiddle](http://jsfiddle.net/aBccw/853/), the sorting is correct. So originally you said that it doesn't throw an error, that's correct, it doesn't, but it also doesn't sort anymore. Originally I pointed this out because it's a bit surprising and I was suggesting adding it to your answer, since it is top of search results for sorting ngOptions. – MushinNoShin Aug 28 '15 at 00:20
  • @MushinNoShin ah yes I get what you pointed out thanks! I'm reluctant to add `track by` mainly because it might confuse people. I wasn't even clear what it did based on the documentation until testing it out a few times. Feel free to edit the answer and the community can decide to accept/reject the changes! Thanks! – Gloopy Aug 28 '15 at 15:54
  • somehow orderBy isn't working for me here. trackBy works. Everything else works. It just doesn't sort the list :-( – ProblemsOfSumit Nov 06 '15 at 16:16
26

You should be able to use filter: orderBy

orderBy can accept a third option for the reverse flag.

<select ng-option="item.name for item in items | orderBy:'name':true"></select>

Here item is sorted by 'name' property in a reversed order. The 2nd argument can be any order function, so you can sort in any rule.

@see http://docs.angularjs.org/api/ng.filter:orderBy

Aaron Lelevier
  • 19,850
  • 11
  • 76
  • 111
Tosh
  • 35,955
  • 11
  • 65
  • 55
2
var module = angular.module("example", []);

module.controller("orderByController", function ($scope) {
    $scope.orderByValue = function (value) {
        return value;
    };

    $scope.items = ["c", "b", "a"];
    $scope.objList = [
        {
            "name": "c"
        }, {
            "name": "b"
        }, {
            "name": "a"
        }];
        $scope.item = "b";
    });

http://jsfiddle.net/Nfv42/65/

TechnoCrat
  • 710
  • 10
  • 20
  • 2
    A bit of text explaining how this answers the OP's question and/or how you would use it would be very helpful here. – Sean the Bean May 11 '16 at 19:50
  • @SeantheBean i have already given fiddle demo so i have not given explaination. – TechnoCrat May 12 '16 at 10:03
  • 2
    @TechnoCrat An explanation would be preferrable anyway. In fact, it would be particularly interesting to know why this solution would be preferred over the ones posted years earlier. Or, how it differs at all... – Chipowski Jul 08 '16 at 12:58
  • @Chipowski ok. going forward i will try to give explanation along with answer. – TechnoCrat Feb 15 '17 at 09:10
0

For anyone who wants to sort the variable in third layer:

<select ng-option="friend.pet.name for friend in friends"></select>

you can do it like this

<select ng-option="friend.pet.name for friend in friends | orderBy: 'pet.name'"></select>
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
Trieu Nguyen
  • 933
  • 1
  • 11
  • 17