7

My application was built on Angular JS and has a lot AJAX requests on server. For example, in PHP I format output array like as:

$dialog[$userId] = array(
   'time' => $key,
   'message' => $message['message'],
   'name_user'  => $info['name']
);

echo json_encode($dialog); die();

But in Angular JS I get not array but object:

549: Objectid_user: "549"message: "Hello"name_user: "Ali Akhmedov"time: 1432070505

Problem that if use ng-repeat then does not work sorting for object. Why in PHP I set array but on client get object?

What easy way to convert object to array? Because I have a lot objects on page from AJAX.

8
  • 2
    json_encode parses associate arrays in php as objects in json. Commented May 22, 2015 at 9:11
  • Associative arrays are (JS-)objects. It's not clear what kind of data you want, are you happy with [1432070505, "Hello", "Ali Akhmedo"]? Commented May 22, 2015 at 9:11
  • Okay, what is way to resolve problem? Commented May 22, 2015 at 9:13
  • I want that work orderBy in ng-repeat for object with key: 549: Objectid_user: "549"message: "Hello"name_user: "Ali Akhmedov"time: 1432070505 Commented May 22, 2015 at 9:14
  • 1
    @vaved In PHP, make sure you have only numeric keys in $dialog, and every key between 0 and the highest id is set, then json_encode will output an array. Commented May 22, 2015 at 9:17

3 Answers 3

11

You don't need to convert object to array in order to iterate over it in ng-repeat. You can just use the following syntax:

<div ng-repeat="(key, value) in items">{{key}} => {{value}}</div>

Documentation of ngRepeat.

Unfortunately, this approach will not work with orderBy filter. To iterate over object properties in specific order, you need to implement your own filter. It may be something like that:

JavaScript

angular.module('app', []).
  filter('orderByKey', ['$filter', function($filter) {
    return function(items, field, reverse) {
      var keys = $filter('orderBy')(Object.keys(items), field, reverse),
          obj = {};
      keys.forEach(function(key) {
        obj[key] = items[key];
      });
      return obj;
    };
  }]);

HTML

<div ng-repeat="(key, value) in items | orderByKey:'-'">{{key}} => {{value}}</div>

Plunker

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

However even this approach will work only starting from 1.4.x, since as it is stated in documentation, AngularJS prior to 1.4.x will sort object properties in alphabetic order while iterating over them in ngRepeat.

In order to make it work in Angular 1.3.x or even 1.2.x you may perform conversion of object to array of objects, each one of which will contain key and value properties. That way you will be able to use it in ngRepeat in combination with filters including orderBy. Here is a code:

JavaScript

angular.module('app', []).
  factory('srv', ['$http', function($http) {
    var items = [],
        loaded = false;
    return {
      getItems: function() {
        if(!loaded) { // Lazy loading
          $http.get('data.json').success(function(data) { // {key1: 'val1', key2: 'val2'}
            Object.keys(data).forEach(function(key) {
              items.push({key: key, value: data[key]});
            });
          });
          loaded = true;
        }
        return items; // [{key: 'key1', value:'val1'}, {key:'key2', value: 'val2'}]
      }
    };
  }]).
  controller('ctrl', ['$scope', 'srv', function($scope, srv) {
    $scope.items = srv.getItems();
  }]);

HTML

<div ng-repeat="item in items | orderBy:'-key'">{{item.key}} => {{item.value}}</div>

Plunker

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

Sign up to request clarification or add additional context in comments.

3 Comments

But if I want to show data sorted from latest to oldest? I tried -key and +key have not difference. Des not work
@vaved I updated the answer with two additional solutions for angular 1.4.x and earlier versions. Please take a look, it works with filters as well.
This works, but isn't this technically not valid because it relies on JavaScript maintaining the insertion order of object properties, which is not guaranteed?
5

Let's say you have an object like:

$scope.myObj = {type:"Fiat", model:500, color:"white"};

Then, in your angular Controller you can do something like:

$scope.array = [];
angular.forEach($scope.myObj, function(element) {
  $scope.array.push(element);
});

and then in your HTML

<div ng-repeat="obj in array">{{obj}}</div>

Here is a demo plunker

Comments

1

orderBy is a filter, and filters require an array. So a straightforward solution is to combine it with a toArray filter. Supposing you want to order your objects using their time property:

<ol>
  <li ng-repeat="value in objectWithValues | toArray | orderBy: 'time'">
    {{value.name_user}} said <q>{{value.message}}</q> on {{value.time|date}}
  </li>
</ol>

As the toArray filter is not shipped with AngularJS, you can define one as:

angular.module('ToArrayDemo', [])
  .filter('toArray', function() {
    return function(obj) {
      const result = [];
      angular.forEach(obj, function(val) {
        result.push(val);
      });
     return result;
   }
 });

See https://plnkr.co/edit/E857InfrEGqToW0SvwOh?p=preview

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.