Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

angularjs 1.5: How to enable auto-sort on key value object?

I recently upgraded my application from angularjs v1.2 to v1.5. On v1.2 angularjs was auto sorting key/value based objects in drop-down. But now as I upgraded to 1.5 every drown on my web app is showing items in random order (i.e. order coming from db). Is there any global parameter I can enable in 1.5 to get that auto-sort functionality again?

app.controller('MainCtrl', function($scope) {
  $scope.days = {
    'key1': 'val1',
    'key7': 'val7',
    'key3': 'val3',
    'key9': 'val9',
    'key2': 'val2',
    'key5': 'val5',
    'key4': 'val4',
  };
});

I created plunk for both versions to ellaborate the problem clearly,

ver 1.2 https://plnkr.co/edit/o0KJXjW25nlvDoKliHV0?p=preview

ver 1.5 https://plnkr.co/edit/TudDwMhaAREhGVl5vz2c?p=preview

like image 935
FarazShuja Avatar asked Mar 26 '26 13:03

FarazShuja


1 Answers

Always have a look at the migration guide before migrating to new version.

On v1.2 angularjs was auto sorting key/value based objects in drop-down. But now as I upgraded to 1.5 every drown on my web app is showing items in random order.

From MDN article

The for...in statement iterates over the enumerable properties of an object, in arbitrary order.

In AngularJS 1.5.0, ng-options directive used getOptionValuesKeys() method to get the array of keys. In that method, they used for...in that does not guarantee the order of iteration. That is why values in the drop-down are not sorted.

function getOptionValuesKeys(optionValues) {
      var optionValuesKeys;

      if (!keyName && isArrayLike(optionValues)) {
        optionValuesKeys = optionValues;
      } else {
        // if object, extract keys, in enumeration order, unsorted
        optionValuesKeys = [];
        for (var itemKey in optionValues) {
          if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
            optionValuesKeys.push(itemKey);
          }
        }
      }
  return optionValuesKeys;   
}

In AngularJS 1.2.28, ng-options directive used sortedKeys() method to get the array of keys. They also used for...in in this method but sorted the array before returning it.

function sortedKeys(obj) {
  var keys = [];
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      keys.push(key);
    }
  }
  return keys.sort();
}

Is there any global parameter I can enable in 1.5 to get that auto-sort functionality again?

Yes, but may be you shouldn't change. To do this, you have to sort the return value of getOptionValuesKeys method in AngularJS source code. Modified method should look like this:

function getOptionValuesKeys(optionValues) {
       var optionValuesKeys;

       if (!keyName && isArrayLike(optionValues)) {
            optionValuesKeys = optionValues;
       } else {
            // if object, extract keys, in enumeration order, unsorted
            optionValuesKeys = [];
            for (var itemKey in optionValues) {
                if (optionValues.hasOwnProperty(itemKey) && itemKey.charAt(0) !== '$') {
                  optionValuesKeys.push(itemKey);
                }
            }
       }
  return optionValuesKeys.sort();
 }

Additional question may arise: Why Angular team made this change?

Migrating from 1.3 to 1.4: Have a look at the changes in ngOptions

Due to 7fda214c, when iterating over an object's properties using the (key, value) in obj syntax the order of the elements used to be sorted alphabetically. This was an artificial attempt to create a deterministic ordering since browsers don't guarantee the order. But in practice this is not what people want and so this change iterates over properties in the order they are returned by Object.keys(obj), which is almost always the order in which the properties were defined.

Note:

This change was made in AngularJS 1.4.0, not in 1.5.0. As you are migrating from 1.2.28, you should consider all changes from version 1.3.0 to 1.5.0.

like image 128
Khalid Hussain Avatar answered Mar 28 '26 02:03

Khalid Hussain



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!