Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get ng-repeat to use object property order

Tags:

angularjs

I have a dynamic dataset to present with Angular. In other words I do not have access to the column names returned until runtime.

I can present the column names as a header and the data itself with no problem. ng-repeat (or perhaps it's JS itself) though refuses to return the columns in the order they were created. You can see in the fiddle the columns are sorted so they appear "age name weight", I need them the way they came, "name age weight"

I created another array of the column names and their proper order ($scope.order) but I cannot seem to find a way to use that with Angular to sort the data.

Please give me a way to present this data in the original order.

I created a JSFiddle: http://jsfiddle.net/GE7SW/

Here's a simple scope that sets up the data:

function MainCtrl($scope) {
$scope.output = [
    {
        "name": "Tom",
        "age": "25",
        "weight" : 250
    },
    {
        "name": "Allan",
        "age": "28",
        "weight" : 175
    },
    {
        "name": "Sally",
        "age": "35",
        "weight" : 150
    }
];

$scope.order = {
    "name": 1,
    "age": 2,
    "weight" : 3
};           
}

Here's the HTML:

<table ng-app ng-controller="MainCtrl">
  <thead>
    <tr>
      <th ng-repeat="(key,value) in output.0">{{key}}</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="row in output">          
      <td ng-repeat="(key,value) in row">{{value}}</td>
    </tr>
  </tbody>
</table>

(Note the (key,value) in the last ng-repeat is needed by ng-class code I took out for this example.)

like image 648
James Bell Avatar asked Nov 18 '13 05:11

James Bell


2 Answers

The properties order in JavaScript objects is never guaranteed. You need to use a list.

The only thing you need to do is convert $scope.order into an array:

$scope.order = [
    "name",
    "age",
    "weight"
];

and use that inside the HTML like this:

<table ng-app ng-controller="MainCtrl">
  <thead>
    <tr>
        <th ng-repeat="key in order">{{key}}</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="row in output">          
      <td ng-repeat="key in order">{{row[key]}}</td>
    </tr>
  </tbody>
</table>    

Fiddle

like image 172
AlwaysALearner Avatar answered Nov 05 '22 14:11

AlwaysALearner


Your updated fiddle here (click).

While the order of javascript objects is not guaranteed, this is likely to work in most or all cases. This is simply looping your objects into arrays. It might be a better approach, if possible, to have the data coming from the server in arrays, 1 that describes the structure (keys) and the other that just data sets of arrays.

$scope.getRow = function(row) {
  var arr = [];
  for (var k in row) {
    if (k !== '$$hashKey') {
      arr.push(row[k]);
    }
  }
  return arr;
};
$scope.getKeys = function(row) {
  var arr = [];
  for (var k in row) {
    if (k !== '$$hashKey') {
      arr.push(k);
    }
  }
  return arr;
};

the html:

<table ng-app ng-controller="MainCtrl">
  <thead>
    <tr>
      <th ng-repeat="(key,value) in getKeys(output[0])">{{value}}</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="row in output">          
      <td ng-repeat="(key, value) in getRow(row)" ng-class="getKeys(output[0])[key]">{{value}}</td>
    </tr>
  </tbody>
</table>
like image 32
m59 Avatar answered Nov 05 '22 15:11

m59