Search code examples
javascriptangularjssortingng-options

Weird sort behaviour when using custom sort filter on ng-options


I'm having issues using my custom sort filter together with ng-options on a select element. The problem is that it doesn't sort my numeric value as it should.

You can see the issue in the plnkr below, it should sort on the 'id' value, but the sorting in the select element is very strange.

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

var app = angular.module('testApp', []);

app.filter('sortKeyIds', function() {
    return function(input) {
      
        //Copy original list
        var keys = input.concat([]);
        
        keys.sort(function(a, b) {
            return a.id - b.id;
        });
        
        return keys;
    }
});

app.controller('MainController', function($scope) {
    $scope.controllerName = "MainController";
    $scope.months = [
      {"id":15,"val":"15x250"},
      {"id":88,"val":"88x31"},
      {"id":120,"val":"120x90"},
      {"id":125,"val":"125x125"},
      {"id":160,"val":"160x600"},
      {"id":180,"val":"180x150"},
      {"id":234,"val":"234x60"},
      {"id":240,"val":"240x400"},
      {"id":250,"val":"250x250"},
      {"id":300,"val":"300x100"},
      {"id":336,"val":"336x280"},
      {"id":468,"val":"468x60"},
      {"id":720,"val":"720x300"},
      {"id":728,"val":"728x90"},
      {"id":980,"val":"980x300"},
      {"id":1250,"val":"1250x250"}
      ];
});

<!-- begin snippet: js hide: false console: true babel: false -->
<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="utf-8" />
    <title>AngularCameraApp</title>
    <link rel="stylesheet" href="style.css" />
    <script src="https://code.angularjs.org/1.3.15/angular.js"></script>
  </head>

  <body ng-app="testApp" ng-controller="MainController">
    <h3>Weird sorting</h3>
    <select ng-model="avtripExpMonth" ng-options="value.lang as value.val for (key, value) in months | sortKeyIds"></select>
  </body>

</html>


Solution

  • var app = angular.module('testApp', []);
    
    /* You could remove this part.
    app.filter('sortKeyIds', function() {
        return function(input) {
          
            //Copy original list
            var keys = input.concat([]);
            console.log(keys);
            keys.sort(function(a, b) {
                return a.id - b.id;
            });
            
            return keys;
        }
    });*/
    
    app.controller('MainController', function($scope) {
        $scope.controllerName = "MainController";
        $scope.months = [
          {"id":15,"val":"15x250"},
          {"id":88,"val":"88x31"},
          {"id":120,"val":"120x90"},
          {"id":125,"val":"125x125"},
          {"id":160,"val":"160x600"},
          {"id":180,"val":"180x150"},
          {"id":234,"val":"234x60"},
          {"id":240,"val":"240x400"},
          {"id":250,"val":"250x250"},
          {"id":300,"val":"300x100"},
          {"id":336,"val":"336x280"},
          {"id":468,"val":"468x60"},
          {"id":720,"val":"720x300"},
          {"id":728,"val":"728x90"},
          {"id":980,"val":"980x300"},
          {"id":1250,"val":"1250x250"}
          ];
    });
    /* Styles go here */
    
    .one {
      font-size:2em;
    }
    .two {
      color:red;
    }
    .aclass {
      text-align:center;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <!DOCTYPE html>
    <html lang="en">
    
      <head>
        <meta charset="utf-8" />
        <title>AngularCameraApp</title>
        <script data-require="jquery@*" data-semver="3.0.0" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0/jquery.js"></script>
        <link rel="stylesheet" href="style.css" />
        <script src="https://code.angularjs.org/1.3.15/angular.js"></script>
        <script src="https://code.angularjs.org/1.3.15/angular-route.js"></script>
        <script src="script.js"></script>
      </head>
    
      <body ng-app="testApp" ng-controller="MainController">
        <h3>Weird sorting</h3>
        <select ng-model="avtripExpMonth" ng-options="month.val for month in months track by month.id | orderBy:month.id"></select>
        <ul id="preview"></ul>
      </body>
    
    </html>

    you could use the orderBy filter by Angular. not sure why you want to use a custom filter for a trivial task.

    does this fiddle work for you. i didn't really understand your (key, value). this is how i'd do it.