Javascript 带空字段的AngularJS orderby

Javascript 带空字段的AngularJS orderby,javascript,angularjs,Javascript,Angularjs,我正在订购一个我的数据,它的工作都是正确的,除了一些字段是空的或没有价值。当命令发出时,这些空字段首先出现。例如,在对数字进行排序时,在得到“0”值之前,我们会得到一个巨大的空列表 我是这样做的: ng-click="predicate = 'name'; reverse=!reverse" 及 JSFiddle: 有没有一个简单优雅的方法来解决这个问题?不管怎样,我希望空字段排在最后。我会编写一个过滤器,从有序数组中提取名称为空的项,并将它们放在末尾: <li ng-repeat="i

我正在订购一个我的数据,它的工作都是正确的,除了一些字段是空的或没有价值。当命令发出时,这些空字段首先出现。例如,在对数字进行排序时,在得到“0”值之前,我们会得到一个巨大的空列表

我是这样做的:

ng-click="predicate = 'name'; reverse=!reverse"

JSFiddle:


有没有一个简单优雅的方法来解决这个问题?不管怎样,我希望空字段排在最后。

我会编写一个过滤器,从有序数组中提取名称为空的项,并将它们放在末尾:

<li ng-repeat="item in (items|orderBy:'name'|emptyToEnd:'name')">{{item.name}}</li>

顺便说一下,你的小提琴没有包含任何相关的代码。你用错链接了吗

更新2:

我不相信有“开箱即用”的解决方案。我很可能错了。 以下是我尝试使用函数作为谓词的解决方案:

ng-repeat="name in names | orderBy:predicate"
在控制器内部:

$scope.predicate = function(name) {
    return name === '' ? 'zzzzzzz' : !name; 
    /* The 'zzzzzz' forces the empty names to the end, 
      I can't think of a simpler way at the moment. */
}

@Klaster_1真的很有意思,但只要我需要一个嵌套值,过滤器就停止工作了。另外,如果我是反向排序的,我仍然希望我的null值显示在0之前。我添加了$parse来处理嵌套键,并添加了一个反向参数,以便我知道何时将空值放在顶部

.filter("emptyToEnd", function ($parse) {
    return function (array, key, reverse) {
        if(!angular.isArray(array)) return;
        var keyFn = $parse(key);
        var present = [];
        var empty = [];

        angular.forEach(array, function(item){
          var val = keyFn(item);
          if(angular.isUndefined(val) || val === null) {
            empty.push(item);
          } else {
            present.push(item);
          }
        });

        if (reverse) {
          return present.concat(empty);
        } else {
          return empty.concat(present);
        }
    };
});

除了Klaster_1的解决方案外,还添加了一个额外的参数以使过滤器更通用:

实施

<tr ng-repeat="name in (names | orderBy:predicate:reverse | orderEmpty:'name':'toBottom')">
Thnx Klaster_1

在下面!:D 此解决方案扩展了angularJs
orderBy
过滤器的正常功能,以获取第三个参数,指定是否反转空值和未定义值的正常排序。它观察所传递的属性名(不仅仅是一个),并且不会像其他一些解决方案那样在项目上迭代一秒钟。它是这样使用的:

.filter("emptyToEnd", function () {
    return function (array, key) {
        if(!angular.isArray(array)) return;
        var present = array.filter(function (item) {
            return item[key];
        });
        var empty = array.filter(function (item) {
            return !item[key]
        });
        return present.concat(empty);
    };
});
<li ng-repeat="item in (items|orderBy:'name':false:true)">{{item.name}}</li>
$scope.convertNullToBlank = function (array) {
  for (var i = 0; i < array.length; i++) {
     if (array[i].col1 === null)
       array[i].col1 = '';

     if (array[i].col2 === null)
        array[i].col2 = '';
  }
  return array;
}
要逐字使用此代码,请指定“lib”作为应用程序的依赖项

归功于:


我不知道为什么其他答案建议将空值记录放在底部,如果我想正常排序,意味着按ASC顺序将所有空值放在顶部,按DESC顺序将所有空值放在底部,我在此处尝试了其他答案,但无法帮助我更改代码以将数组中的null转换为“”,现在它的工作方式如下:

.filter("emptyToEnd", function () {
    return function (array, key) {
        if(!angular.isArray(array)) return;
        var present = array.filter(function (item) {
            return item[key];
        });
        var empty = array.filter(function (item) {
            return !item[key]
        });
        return present.concat(empty);
    };
});
<li ng-repeat="item in (items|orderBy:'name':false:true)">{{item.name}}</li>
$scope.convertNullToBlank = function (array) {
  for (var i = 0; i < array.length; i++) {
     if (array[i].col1 === null)
       array[i].col1 = '';

     if (array[i].col2 === null)
        array[i].col2 = '';
  }
  return array;
}
$scope.convertNullToBlank=函数(数组){
对于(var i=0;i
这个字符串排序方法如何:

item in (items|orderBy:['!name', 'name'])

优势(除了更简洁),它使用空白字符串排序<代码> null < /C> > <代码>未定义< /代码>。 在我的例子中,我希望空格、null和未定义项一起位于顶部(默认情况下,null和未定义项排序在底部),因此我使用:

item in (items|orderBy:['!!name', 'name'])
排序和反向排序,使用变量排序列,并在底部保留未定义的值,甚至低于负值 我喜欢上面肖恩回答的优雅!我需要让我的用户能够选择要排序的列,以及选择排序方向,但仍然需要将未定义的列降到底部,即使有负数

肖恩修复负数的关键洞见是!!。使用“!”+谓词,如果您正在进行正向排序和“!!”+如果正在进行反向排序,则谓词

下面的代码片段演示了这一点。顺便说一句,我将设置谓词(选择要排序的属性)和反转的变量放在对象(“d”)中,这样我们就不会遇到奇怪的范围问题。在您的环境中可能不需要“d”

此外,您可能希望使用比我在页面底部的蹩脚按钮更好的方法来控制排序谓词和方向。然而,这使得代码的关键部分易于阅读

功能主控制器($scope){
$scope.userArray=[
{姓名:“堂”,年龄:20},
{姓名:“鲍勃”,年龄:30岁,身高:170},
{姓名:“Abe”,年龄:40岁,身高:160},
{姓名:“佐伊”,年龄:70},
{年龄:70,身高:155},
{姓名:“矮子”,年龄:45岁,身高:-200},
{姓名:“TwinkleInEye”,年龄:-1岁,身高:152}
]
$scope.d={};//创建一个对象,该对象可以存储信息,而不会被Angular添加作用域的倾向所破坏
$scope.d.predicate=“name”//此字符串是要排序的属性的名称
$scope.d.reverse=false;//True表示颠倒排序顺序
}

名称{{user.Name}:年龄{{user.Age}}:高度{{user.Height}

名称 年龄 当前高度:{d.predicate}
在底部保留未定义,否则: 当前反向:{d.Reverse}
我根据以前的解决方案创建了一个带有替代过滤器的要点:

该过滤器扩展了现有的角度过滤器:

angular.module 'tsd.orderByEmptyLast', []
  .filter 'orderByEmptyLast', ($filter) ->
    return (list, predicate, reverse)->
      orderedList = $filter('orderBy')(list, if reverse then ['!' + predicate, '-' + predicate] else ['!' + predicate, predicate] )
      return orderedList
在较新的angular版本中,您可能需要包括
orderByFilter
,而不是使用$filter

angular.module 'tsd.orderByEmptyLast', ['orderByFilter']
  .filter 'orderByEmptyLast', () ->
    return (list, predicate, reverse)->
      orderedList = orderByFilter(list, if reverse then ['!' + predicate, '-' + predicate] else ['!' + predicate, predicate] )
      return orderedList

抱歉,用正确的小提琴编辑。我如何将你的例子与我的小提琴结合起来?@deekay,do
myApp.filter(“emptyToEnd…
我添加了一个链接来摆弄集成过滤器。很酷!为什么我会收到一个错误类型错误:无法调用undefined at对象的“filter”方法。在我的应用程序中?如果你想将零作为一个值,而不将其归类为空交换,则此位:var present=array.filter((项)=>{return item[key]| | item[key]==0;});var empty=array.filter((item)=>{return!item[key]&&item[key]!==0;});注意,这不适用于负数键。这意味着当您使用“-keyToSortOn”此筛选器完全失败。您可以使用
“~”
(ASCII 126)而不是
“zzz…”
。这就像一个符咒。这是迄今为止我发现的唯一一个可以正确处理多个谓词的解决方案。而且它启动起来非常干净。不真实!扩展Angular很有趣