2

I have an object like this:

Object {0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 11, 6: 13, 7: 15, 8: 17, 9: 19, 10: 22, 11: 24, 12: 26, 13: 28, 14: 30, 15: 33, 16: 35, 17: 37, 18: 39, 19: 41, 20: 44, 21: 46, 22: 48, 23: 50, 24: 52, 25: 55, 26: 57, 27: 59, 28: 61, 29: 63, 30: 66, 31: 68, 32: 70, 33: 72, 34: 74, 35: 77, 36: 79, 37: 81, 38: 83, 39: 85, 40: 88, 41: 90, 42: 92, 43: 94, 44: 97, 45: 99, 46: 101, 47: 103, 48: 105, 49: 108, 50: 110, 51: 112, 52: 114, 53: 116, 54: 119, 55: 121, 56: 123, 57: 125, 58: 127, 59: 130, 60: 132, 61: 134, 62: 136, 63: 138, 64: 141, 65: 143, 66: 145, 67: 147, 68: 149, 69: 152, 70: 154, 71: 156, 72: 158, 73: 160, 74: 163, 75: 165, 76: 167, 77: 169, 78: 171, 79: 174, 80: 176, 81: 178, 82: 180, 83: 182, 84: 185, 85: 187, 86: 189, 87: 191, 88: 194, 89: 196, 90: 198, 91: 200, 92: 202, 93: 205, 94: 207, 95: 209, 96: 211, 97: 213, 98: 216, 99: 218…}

and I'm using it in ng-options for select box. But I got them rendered in wrong order:

1 10 100 101 ... 11 110

How can I sort values in select box as integers? In common, I should use natural sorting function. Something like this https://github.com/overset/javascript-natural-sort/blob/master/naturalSort.js However I have only numbers in this list and maybe there are simplier solution in my case?

Maybe it is possible in some way to make angular treat objects keys and integers?

Here is the plunkr: http://plnkr.co/edit/mUBM0egiS8pl8odaWQQY?p=preview

SET001
  • 11,480
  • 6
  • 52
  • 76

2 Answers2

9

You have to convert the list to an array to guarantee sort order. You cannot guarantee sort order using an Object hashmap, it just doesn't work that way.

The best bet — performance wise — is to convert the object in the controller:

var values = {...}
$scope.selectOptions = [];
angular.forEach(values, function(value, key) {
    $scope.selectOptions.push({
        key: value,
        label: key
    });
});
$scope.selectOptions.sort(mySortingFunction);

In your view:

<select model="selected" ng-options="opt.key as opt.label for opt in selectOptions"></select>

This will create a select where the labels are the original object's property keys and the values are the original object's property values.

If you want the rearranging to occur on the fly, you can do it as a filter, but be prepared for potential performance issues.

app.filter("naturalSortedObject", function() {
    return function(obj) {
        var result = [];
        angular.forEach(obj, function(value, key) {
            result.push({
                key: value,
                label: key
            });
        });
        result.sort(mySortingFunction);
        return result;
    }
});

Then use it like this:

<select model="selected"
    ng-options="opt.key as opt.label for opt in selectOptions | naturalSortedObject"></select>

Also, you already have a natural sorting algorithm, but if you want one that's already designed to be used as an Angular filter & module, I wrote one. It integrates pretty well, and can be used in a caching manner to make it a little faster.

Community
  • 1
  • 1
OverZealous
  • 39,252
  • 15
  • 98
  • 100
1

You can try this:

Javascript

self.foo = []
angular.forEach [9..364], (i, el) ->
    self.foo.push({ key: el, value: ~~(el / 0.45359237) })

HTML

<select ng-options="item.value as item.key for item in foo" ng-model="w"></select>
Michael Benford
  • 14,044
  • 3
  • 60
  • 60