【问题标题】:Why is angular orderBy custom comparator not working?为什么 angular orderBy 自定义比较器不起作用?
【发布时间】:2016-07-01 09:05:45
【问题描述】:

我正在尝试为角度 orderBy 指令实现自定义比较器。正如您在代码 sn-p 中看到的,自定义比较器被忽略(没有从 console.log 记录任何内容),即使它应该根据 angular documentation for orderBy

工作

angular.module('orderByExample', [])
.controller('ExampleController', ['$scope', function($scope) {
  $scope.files = [
    {name: 'File1', size: '1.2 Mb'},
    {name: 'File2', size: '2.4 Kb'},
    {name: 'File3', size: '241 Bytes'},
    {name: 'File4', size: '2.0 Mb'},
    {name: 'File5', size: '16.1 Kb'}
  ];

  $scope.fileSizeComparator = function(s1, s2) {
    // split the size string in nummeric and alphabetic parts
    console.log(s1);
    console.log(s2);
    var s1Splitted = s1.size.split(" ");
    var s2Splitted = s2.size.split(" ");
    if (s1Splitted[1] === s2Splitted[1]) {
      // if size type is the same, compare the number
      return s1Splitted[0] > s2Splitted[0];
    }
    // default : compare on size type Mb > Kb > Bytes
    return s1Splitted[1] > s2Splitted[1];
  };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="orderByExample">
  <div ng-controller="ExampleController">
    <table>
      <tr>
        <th>Name</th>
        <th>Size</th>
      </tr>
      <tr ng-repeat="file in files | orderBy:'size':false:fileSizeComparator">
        <td>{{file.name}}</td>
        <td>{{file.size}}</td>
      </tr>
    </table>
  </div>
</div>

我已经在JsFiddle 上测试了角度文档中的示例代码,但它也不起作用。 有什么想法吗?

【问题讨论】:

  • 查看角度文档的最后一个示例,它说第三个参数应该作为函数读取

标签: javascript angularjs sorting angularjs-orderby


【解决方案1】:

在@morels 的帮助下,我找到了解决方案:是的,我确实应该返回 1 和 -1。但主要问题是比较器被忽略了。显然这是因为此功能仅适用于 angular 1.5.7 及更高版本。 我还需要在s1和s2的传递参数的.value上使用.split

这是代码 sn-p 中的工作解决方案:

angular.module('orderByExample', [])
.controller('ExampleController', ['$scope', function($scope) {
  $scope.files = [
    {name: 'File1', size: '1.2 Mb'},
    {name: 'File2', size: '2.4 Kb'},
    {name: 'File3', size: '241 Bytes'},
    {name: 'File4', size: '2.0 Mb'},
    {name: 'File5', size: '16.1 Kb'}
  ];

  $scope.fileSizeComparator = function(s1, s2) {
    // split the size string in nummeric and alphabetic parts
    var s1Splitted = s1.value.split(" ");
    var s2Splitted = s2.value.split(" ");
    if (s1Splitted[1] === s2Splitted[1]) {
      // if size type is the same, compare the number
      return parseFloat(s1Splitted[0]) > parseFloat(s2Splitted[0]) ? -1 : 1;
    }
    // default : compare on size type Mb > Kb > Bytes
    return s1Splitted[1] > s2Splitted[1] ? -1 : 1;
  };
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<div ng-app="orderByExample">
  <div ng-controller="ExampleController">
    <table>
      <tr>
        <th>Name</th>
        <th>Size</th>
      </tr>
      <tr ng-repeat="file in files | orderBy:'size':false:fileSizeComparator">
        <td>{{file.name}}</td>
        <td>{{file.size}}</td>
      </tr>
    </table>
  </div>
</div>

【讨论】:

    【解决方案2】:

    因为你应该返回-1,0,1 而不是true,false

    official documentation 之后,您可以看到典型比较函数的格式

    $scope.localeSensitiveComparator = function(v1, v2) {
    // If we don't get strings, just compare by index
    if (v1.type !== 'string' || v2.type !== 'string') {
      return (v1.index < v2.index) ? -1 : 1;
    }
    
    // Compare strings alphabetically, taking locale into account
    return v1.value.localeCompare(v2.value);   };
    

    请改写为:

    $scope.fileSizeComparator = function(s1, s2) {
        // split the size string in nummeric and alphabetic parts
        console.log(s1);
        console.log(s2);
        var s1Splitted = s1.size.split(" ");
        var s2Splitted = s2.size.split(" ");
        if (s1Splitted[1] === s2Splitted[1]) {
          // if size type is the same, compare the number
          if ( s1Splitted[0] > s2Splitted[0])
            return 1;
          else 
           return -1;
        }
        // default : compare on size type Mb > Kb > Bytes
        return s1Splitted[1] > s2Splitted[1] ? -1 : 1;
      };
    

    请注意,您永远不会错过平等,即0

    【讨论】:

    • 我发现主要问题是角度版本。显然,自定义比较器需要 angular 1.5.7 才能工作。不过感谢您的帮助,我确实应该返回 1 或 -1 而不是 true 或 false。
    【解决方案3】:

    这样做

    ng-repeat="file in files | orderBy: sizeFilter: true"
    
    $scope.sizeFilter=function(file){
            $scope.size = file.size;
            return $scope.size;
    };
    

    【讨论】:

    • 这无缘无故地引入了一个新的范围变量“size”。也完全错过了OP使用字符串的Byte,kb,Mb部分的意图。
    猜你喜欢
    • 2013-11-27
    • 2019-02-12
    • 1970-01-01
    • 2021-08-07
    • 2020-06-27
    • 1970-01-01
    • 2013-12-25
    • 2016-12-01
    • 1970-01-01
    相关资源
    最近更新 更多