自定义orderBy用于AngularJS

时间:2016-06-29 15:56:11

标签: angularjs object nested sql-order-by ng-repeat

我正在尝试通过嵌套属性对我的数组中的所有对象进行排序,在我的例子中是validUntil字段。我只是想不通怎么做?

我正在使用带有ng-repeat的角度来循环我的对象。用自定义过滤器扩展它会很棒(所以我可以创建多个orderby字段)

我在SO上搜索但是我没有找到任何关于此类对象结构的好解决方案。

更新 所有validUntil字段都是纪元时间戳。所以我的输出应该像在validUntil字段上升或降。这甚至可能吗?我想我需要打破我的签到并将对象分开并创建一个新阵列来实现这一目标?

[{
  "19852" : {
    "checkins" : {
      "-KJk_QqoIMQi_XT4V-e8" : {
        "called" : false,
        "createdAt" : 1465398937,
        "daysBetween" : 22,
        "new" : 2000,
        "old" : 996,
        "ratio" : 45.54545454545455,
        "type" : "checkins",
        "validUntil" : 1467324000
      }
    },
    "fans" : {
      "-KLL5pZsdZu2lAbmIuED" : {
        "called" : false,
        "createdAt" : 1467102227,
        "daysBetween" : 3,
        "new" : 500,
        "old" : 173,
        "ratio" : 109,
        "type" : "fans",
        "validUntil" : 1467324000
      },
      "-KLLqu_BT6cIVf-ALJMA" : {
        "called" : false,
        "createdAt" : 1467114826,
        "daysBetween" : 2,
        "new" : 600,
        "old" : 174,
        "ratio" : 213,
        "type" : "fans",
        "validUntil" : 1467324000
      }
    },
    "name" : "Test 1"
  },
  "-KCGLvKjmF0dxe8QuAXh" : {
    "checkins" : {
      "-KLRVY9FAzHDPTIf1_qS" : {
        "called" : false,
        "createdAt" : 1467209626,
        "daysBetween" : 32,
        "new" : 4000,
        "old" : 3699,
        "ratio" : 6.9,
        "type" : "checkins",
        "validUntil" : 1470002400
      }
    },
    "name" : "Test 2"
  },
  "-KKOX2JDkM84jrZcHHq4" : {
    "fans" : {
      "-KL253oeqDFedCRpDV4a" : {
        "called" : false,
        "createdAt" : 1466783256,
        "daysBetween" : 6,
        "new" : 10,
        "old" : 1,
        "ratio" : 1.5,
        "type" : "fans",
        "validUntil" : 1467324000
      }
    },
    "name" : "Test 3"
  }
}]

1 个答案:

答案 0 :(得分:1)

AngularJs的OrderBy不允许对象进行排序。要解决这个问题,您可以自己将对象转换为数组,也可以创建一个新的过滤器来在幕后执行此操作。

以下是如何通过自定义过滤器执行此操作。请注意,函数getMinValue是递归的,不处理循环引用(它们将继续旋转)。如果您遇到这个问题,您只需要修改此函数,而不是递归调用某些键。

以下是javascript代码:

angular.module("myApp", []).filter('orderObjectBy', function(orderByFilter) {
  return function(items, sortPredicate, reverseOrder) {
    var array= [];
    angular.forEach(items, function(item) {
      array.push(item);
    });
    return orderByFilter(array, sortPredicate, reverseOrder);
  };
}).controller('someController', function ($scope) {
    $scope.order = function(obj){
        return getMinValue(obj);
    };
    function getMinValue(obj){
        //this is a recursive call that will look through all of the objects to find the minimum validUntil.  Be careful because circular references will loop forever.
        //if you believe you might have circular references, then there are small changes you can make to account for that.  It just didn't seem necessary for your code.
        var minValidUntil = null;
        angular.forEach(obj, function(item) {
            var validUntil = item.validUntil;
            if(validUntil == null && angular.isObject(item)){
                validUntil = getMinValue(item);
            }
            if(validUntil != null && (minValidUntil == null || validUntil < minValidUntil)){
                minValidUntil = validUntil;
            }
        });
        return minValidUntil;
    }
    $scope.data = {
      "19852" : {
        "checkins" : {
          "-KJk_QqoIMQi_XT4V-e8" : {
            "called" : false,
            "createdAt" : 1465398937,
            "daysBetween" : 22,
            "new" : 2000,
            "old" : 996,
            "ratio" : 45.54545454545455,
            "type" : "checkins",
            "validUntil" : 1467324000
          }
        },
        "fans" : {
          "-KLL5pZsdZu2lAbmIuED" : {
            "called" : false,
            "createdAt" : 1467102227,
            "daysBetween" : 3,
            "new" : 500,
            "old" : 173,
            "ratio" : 109,
            "type" : "fans",
            "validUntil" : 1467324000
          },
          "-KLLqu_BT6cIVf-ALJMA" : {
            "called" : false,
            "createdAt" : 1467114826,
            "daysBetween" : 2,
            "new" : 600,
            "old" : 174,
            "ratio" : 213,
            "type" : "fans",
            "validUntil" : 1467324000
          }
        },
        "name" : "Test 1"
      },
      "-KCGLvKjmF0dxe8QuAXh" : {
        "checkins" : {
          "-KLRVY9FAzHDPTIf1_qS" : {
            "called" : false,
            "createdAt" : 1467209626,
            "daysBetween" : 32,
            "new" : 4000,
            "old" : 3699,
            "ratio" : 6.9,
            "type" : "checkins",
            "validUntil" : 1470002400
          }
        },
        "name" : "Test 2"
      },
      "-KKOX2JDkM84jrZcHHq4" : {
        "fans" : {
          "-KL253oeqDFedCRpDV4a" : {
            "called" : false,
            "createdAt" : 1466783256,
            "daysBetween" : 6,
            "new" : 10,
            "old" : 1,
            "ratio" : 1.5,
            "type" : "fans",
            "validUntil" : 1467324000
          }
        },
        "name" : "Test 3"
      }
    };
});

这是我用于测试的html:

<div ng-app="myApp" ng-controller="someController">
    <div ng-repeat='obj in data | orderObjectBy: order'>
        <span>{{obj.name}}</span>
        <div ng-repeat='checkin in obj.checkins'>
            <span>checkin - {{checkin.validUntil}}</span>
        </div>
        <div ng-repeat='fan in obj.fans'>
            <span>fan - {{fan.validUntil}}</span>
        </div>
        <br /><br />
    </div>
</div>