6

I,m trying to ng-repeat nested object properties and order them, but the ordering isn't working for me.

I've seen this: How to orderby in AngularJS using Nested property

but the json structure is different and i couldn't get it to work.

Plunker

My code:

   <div ng-repeat="item in data | orderBy:order.allListPosition">
       <div>{{item.name}} - {{item.order}}</div>
   </div>

The scope:

   $scope.data = {
           "78962": {
                 "id": "78962",
                 "name": "item 2",
                 "type": "blind",
                 "order": {
                       "allListPosition": "008",
                       "catListPosition": "059"
                       },
                 "data": {
                       "status": "stop",
                       "percent": 20
                       },
                 "longPress": {
                       "item": "78966",
                       "active": true
                      }
           },
            "78963": {
                   "id": "78963",
                   "name": "item 3",
                   "type": "coolmaster",
                   "order": {
                         "allListPosition": "053",
                         "catListPosition": "001"
                    },
                    "data": {
                           "status": 1,
                           "temp": 16,
                           "point": 25,
                           "mode": "cool",
                           "fan": 3
                          },
                 "longPress": {
                           "item": "78966",
                           "active": false
                            }
               }
            };

Can anyone please show me what am i doing wrong?

Thank's alot

Avi

Community
  • 1
  • 1
אVי
  • 1,913
  • 6
  • 22
  • 35

4 Answers4

14

There are two reasons orderBy isn't working here:

  • orderBy only works on arrays, but you are applying it to a plain object.
  • To order by an expression, you need to give orderBy a string value with the expression. You are giving it order.allListPosition, which would equate to $scope.order.allListPosition (which doesn't exist).

To solve the first issue, add an array of your data objects:

$scope.dataArray = Object.keys($scope.data)
  .map(function(key) {
    return $scope.data[key];
  });

To solve the second issue (and incorporate the dataArray from above):

<div ng-repeat="item in dataArray | orderBy:'order.allListPosition'">

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

JLRishe
  • 99,490
  • 19
  • 131
  • 169
2

You can create a custom filter to order by neasted properties.

myApp.filter('customorder', function() {
   return function(items) {  
    items.sort(function(a,b){
        // Make sure we are comparing integers
        var aPos = parseInt(a.order.allListPosition);
        var bPos = parseInt(b.order.allListPosition);

        // Do our custom test
        if (aPos  > bPos ) return 1;
        if (aPos < bPos) return -1;         
        return 0; 
    })
   }
 });

Your html will look like

<div ng-repeat="item in data | customorder">
   <div>{{item.name}} - {{item.order}}</div>
</div>

You should always think that angular is not a restritive language. the filters you normally use are built in filters. But you can have fun with your own filter as soon as you need!

nanndoj
  • 6,580
  • 7
  • 30
  • 42
  • Hi, thanks for your answer. because the $scope.data is an object you can't use sort. can you please show me a plunker example? – אVי Jan 05 '15 at 12:22
2

Your data object is an object of objects, and not an array of objects.

Therefore, orderBy won't work since it is only compatible with arrays.

I have updated your data object to make it work:

$scope.data = [
             {              
              "id": "78961",
              "name": "item 1",
              "type": "blind",
              "order":{allListPosition:"093",catListPosition: "009"}, 
              "data": {
                  "status": "up",
                  "percent": 80
              },
              "longPress": {
                  "item": "78966",
                  "active": true
              }

            },
            {  
              "id": "78962", 
              "name": "item 2",
              "type": "blind",
                "order":{allListPosition:"008",catListPosition: "059"},
              "data": {
                  "status": "stop",
                  "percent": 20
              },
              "longPress": {
                  "item": "78966",
                  "active": true
              }
            },
            {

              "id": "78963",
              "name": "item 3",
              "type": "coolmaster",
                "order":{allListPosition:"053",catListPosition: "001"},
              "data": {
                  "status": 1,
                  "temp": 16,
                  "point": 25,
                  "mode": "cool",
                  "fan": 3
              },
              "longPress": {
                  "item": "78966",
                  "active": false
              }

            }];

And in HTML:

<div ng-repeat="item in data | orderBy:'order.allListPosition'">
   <div>{{item.name}} - {{item.order}}</div>
</div>

Plunker

Omri Aharon
  • 16,959
  • 5
  • 40
  • 58
  • Thank's alot but i can't change the data object. that is how i get the data from the api. is there a workaround? – אVי Jan 05 '15 at 12:25
-3

I'm pretty sure this should be:

<div ng-repeat="item in dataArray | orderBy:'item.order.allListPosition'">

Helena
  • 1