21

This is the json that is generated using PHP

[{"Sale":{"id":"1","customer_id":"1","amount":"15","created":"2014-05-17"}}]

Doing orderBy:id is obviously not working. I read in other posts that an orderBy function needs to be created for this kind of data structure. I am not able to create the function. Can anyone please tell me what is the correct way to approach this?

Kelly
  • 40,173
  • 4
  • 42
  • 51
user727728
  • 733
  • 2
  • 8
  • 21
  • 2
    Read [this](http://stackoverflow.com/questions/12040395/angularjs-custom-sort-function-in-ng-repeat). – Sergey Moiseev May 18 '14 at 15:23
  • 1
    You don't need to use a custom orderBy function for this. However, as the value of id is a string it will not sort in the order I assume you want. So you might as well put both the sorting and the int conversion in a custom filter just like @Dalorzo suggested. – tasseKATT May 18 '14 at 16:18

3 Answers3

66

Suppose you have:

$scope.sales = [{"Sale":{"id":"1"}},{"Sale":{"id":"2"}},{"Sale":{"id":"3"}}];

Why not just do following:

<div ng-repeat="sale in sales | orderBy:'Sale.id':true">
    {{ sale.Sale.id }}
</div>

It works well with my case. May be Angular did not support it at the time you asked the question.

KinoP
  • 1,532
  • 15
  • 23
  • 9
    This is a lot more simple than a custom filter. – Chris Foster Nov 05 '15 at 23:31
  • 8
    The trick is to use `| orderBy: 'propertyName.nestedPropertyName'`, wish the angular docs would mention this syntax. – Mike R Oct 05 '16 at 21:43
  • I improved this method by using a dynamically created property in a controller, that holds the sort field and the sort direction. It looks like this `| orderBy:SortController.sort_field:SortController.sort_dir` . The SortController gets updated dynamically. So I even can sort by sub nested properties. – rawdog Jun 18 '21 at 12:28
5

These type of data manipulations I like to keep them in the proper angular objects and for that reason I would create my custom filter, something like:

var sampleSource=  [{"Sale":{"id":"8","customer_id":"1","amount":"15","created":"2014-05-17"}}, {"Sale":{"id":"5","customer_id":"6","amount":"15","created":"2015-05-17"}}];

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

myApp.filter('myFilter', function() {
 return function(items) {  
    items.sort(function(a,b){   
        if (parseInt(a.Sale.id) > parseInt(b.Sale.id))
            return 1;
        if (parseInt(a.Sale.id) < parseInt(b.Sale.id))
            return -1;         
        return 0; })
});

Important: I recommend the custom filter because as personal preference I do not like to overload my controllers or other objects with tasks(code) that I can separate on other objects which gives me more independence and cleaner code(one of the things I love about angular) but besides this personal preference I would say that this is not the only way but if you share my reasons behind it I hope it helps.

ndequeker
  • 7,932
  • 7
  • 61
  • 93
Dalorzo
  • 19,834
  • 7
  • 55
  • 102
0
myapp.filter('orderBySub', function () {
  return function (items, field, reverse) {

    byString = function(o, s) {
        s = s.replace(/\[(\w+)\]/g, '.$1');
        s = s.replace(/^\./, '');
        var a = s.split('.');
        for (var i = 0, n = a.length; i < n; ++i) {
            var k = a[i];
            if (k in o) {
                o = o[k];
            } else {
                return;
            }
        }
        return o;
    }

    items.sort(function (a, b) {
        if (byString(a, field) > byString(b, field))
            return reverse ? -1 : 1;
        if (byString(a, field) < byString(b, field))
            return reverse ? 1 : -1;
        return 0;
    })
    return items;
  }
});

Example

ng-repeat="task in tasks | orderBySub: 'field1.subfield2.subsubfield3':true"

true = reverse

Michalis
  • 6,686
  • 13
  • 52
  • 78