Adrian Florescu
Adrian Florescu

Reputation: 4502

orderBy not working as expected

I am trying to iterate over a JSON response and sort by another key-value pair in the object (the order object value, but looks like that is now working out for me.

Can I reformat the object in another way that I could not think of so far?

I there anything that I can do in Angular?

HTML

<div ng-app="myApp" ng-controller="Ctrl">
    <div ng-repeat="item in myCards">
        <h1>Title: {{item.title}}</h1>

        <div ng-repeat="(blockName, majorBlock) in item.blocks | orderBy:'order'">
            <h2>Name: {{blockName}}, Order: {{majorBlock.order}}</h2>
        </div>

    </div>
</div>

JS

angular.module('myApp', [])
    .controller('Ctrl', function($scope) {
        $scope.myCards =  {
            template: {
                tagline: 'Tagline',
                url: 'url',
                title: 'My Title',
                blocks: {
                    'cover': {
                        "coverUrl": "http://www.url.com/cover/",
                        "coverImage": "http://www.url.com/cover/",
                        "order": '1'
                    },
                    'text': {
                        "headerText": "amet anim est eu enim in incididunt cillum reprehenderit proident",
                        "order": '2'
                    },
                    'products_block': {
                        'order': '3'

                    }

                }
            }
        };
    });

Fiddle: http://jsfiddle.net/fvdb3d3p/

I tried a few hacks, with orderByArray plugin, but they break the rest of the loop.

Upvotes: 1

Views: 67

Answers (1)

Josep
Josep

Reputation: 13071

The problem is that $scope.myCards.template.blocks is an object, not an Array, you can iterate an object with ng-repeat, but the filter orderby only works with arrays, as you can see in the API documentation: https://docs.angularjs.org/api/ng/filter/orderBy

You may want to write a custom filter for this.

EDIT:

I've found this custom filter called "orderObjectBy" from: http://justinklemm.com/angularjs-filter-ordering-objects-ngrepeat/

yourApp.filter('orderObjectBy', function() {
  return function(items, field, reverse) {
    var filtered = [];
    angular.forEach(items, function(item) {
      filtered.push(item);
    });
    filtered.sort(function (a, b) {
      return (a[field] > b[field] ? 1 : -1);
    });
    if(reverse) filtered.reverse();
    return filtered;
  };
});

EDIT:

I've tweaked the original filter function so that you can have access to the key of your object, the tweaked version looks like this:

.filter('orderObjectBy', function() {
  return function(items, field, reverse) {
    var filtered = [];
    angular.forEach(items, function(item, key) {
      item.originalKey = key;
      filtered.push(item);
    });
    filtered.sort(function (a, b) {
      return (a[field] > b[field] ? 1 : -1);
    });
    if(reverse) filtered.reverse();
    return filtered;
  };
})

example: http://jsfiddle.net/fvdb3d3p/2/

Upvotes: 1

Related Questions