【问题标题】:AngularJS orderby refiningAngularJS orderby 精炼
【发布时间】:2016-06-16 16:09:03
【问题描述】:

我有一个以标题(先生、夫人等)开头的姓名和存储为字符串的日期以及一些其他数据的表格。

我目前正在使用

对其进行排序
<tr dir-paginate="booking in bookingResults | orderBy:sortType:sortReverse | filter:searchPassenger | itemsPerPage: 15">

如何优化我的 orderBy 以将不包括标题(先生、夫人等)和日期的名称排序为已解析的日期而不是字符串。

这里的最佳做法是什么?

编辑: 顺便说一句,我不想​​更改模型中的名称-我希望格式保持为“Mr Foo”和“Mr Bar”,但是当我对它们进行排序时,我希望它们表现得好像它们只是“Foo”和“酒吧”。

编辑编辑: AngularJS 1.5.6

【问题讨论】:

  • 所以要明确一点,你所有的名字都是“Mr. Blah”或“Mrs. Foo”,换句话说,你需要先从正确的名字中去掉标题?
  • 仅在排序时,我希望标题显示在表格中但不影响排序顺序。是的,我们得到的数据库条目是一个字符串。我可以轻松地去掉显示器中的 Mr 或 Mrs,但这不会影响模型。此外,我正在寻找一种方法,可以对同一张表的不同列使用不同的排序规则。希望现在稍微清楚一点

标签: angularjs angularjs-filter angularjs-orderby


【解决方案1】:

以正确的格式获取正确的数据

标题和名称

我会使用正则表达式从名称中提取标题:

var regex = /((Dr\.|Mr\.|Ms\.|Miss|Mrs\.)\s*)/gmi
objName.replace(regex, '')

日期

我假设您获取的是日期对象或标准日期字符串。如果是后者,只需通过new Date(incomingDateString) 创建一个 Date 对象。然后你可以调用:

objDate.getTime() //returns epoch in milliseconds

排序

有些人可能不喜欢这个,但我讨厌使用 NG 指令需要用于排序等事情的方法来弄脏视图控制器。相反,我在每个行项上使用 ng-init 添加了一些 ng-flagged 属性。然后我可以根据它进行排序。我没有针对示例中的日期执行此操作,但您可以推断并应用。

ng-init w。 ng 标记 属性

<tr ng-repeat="row in vc.listData | orderBy:vc.sortKey track by $index"
    ng-init="row.$name = row.name.replace(vc.regexp, '')">

所以换句话说,你的对象来自这个:

{ 
    name:'Mr. Fred Rogers', 
    date:<date-object> 
}

感谢ng-init

{ 
    name:'Mr. Fred Rogers', 
    date:<date-object>, 
    $name:'Fred Rogers', 
    $date:1466192224091 
}

然后通过您的排序 UI,您可以将您的 $scope.sortKey 设置为 $name$date

代码笔

我用代码笔制作了一个示例,但我使用的是咖啡脚本和玉石模板。你大概能猜到我在做什么。

笔-http://codepen.io/jusopi/pen/aZZjgG?editors=1010

【讨论】:

  • 这是一个好方法,但我不想更改模型中的名称,我仍然希望它看起来像“Mr Blah”和“Mr Foo”,但我希望它们排序为“废话”和“富”。我想我应该写一个过滤器什么的,我正在研究它。无论如何,感谢您的努力,我对此投了赞成票,我会回来尝试至少再实施一次,但我认为这不是我正在寻找的答案。
  • 您不必更改模型上的名称。 namedate 值与您从服务中获取它们时的值相同。 ng-init 只是动态地为您的模型创建新属性。这也使您不必 a) 在控制器上添加比较器方法 b) 更容易跟踪问题。
  • 我再次尝试了您的 codepen,由于某种原因它今天早上没有打开,是的 - 现在我明白了。我将您的答案标记为答案。我唯一要问的是,您的方法是否会对性能产生负面影响?如果表很大并且用户实际上并不是每次都进行排序怎么办?我认为比较器解决方案更擅长将逻辑与视图分离。否则感谢您的努力!
  • 我在这里做一个有根据的猜测,因为我没有使用比较器功能,也没有使用 NG1.5.7。在每一行的模型上添加 2 个额外的属性并遵循更简单的排序逻辑而不是通过比较器对象运行对象(尤其是您的答案的复杂性之一),我必须打赌我的方法会更高效。如果我们谈论几百行,我认为你不会注意到任何一种方式。如果我们说的是几千,那么是的,认为会很明显。但到那时你无论如何都会对它们进行分页。
  • 另外,plunkr 和 codepen 有时会停止工作。我已经向 plunkr 发了推文,他在半天内解决了这个问题。可能是服务器问题...谁知道呢。
【解决方案2】:

好的,经过一番研究,我发现最简单的解决方案是升级到 AngularJS 1.5.7 版,它将comparator 引入orderBy 过滤器。

所以我改变了我的中继器以使用比较器的顺序

<tr dir-paginate="booking in Results | orderBy:Variable:TrueOrFalse:bookingComparator">

Variable 是我绑定到表格标题的字符串,因此您可以通过键更改顺序,TrueOrFalse 是交替的布尔值如果您单击表格标题并且 bookingComparator 是我的实际比较器,则在升序和降序之间。

我的预订比较器看起来像这样

   $scope.bookingComparator = function (a, b) {
        var getTitle = /((Mrs|Mr|Mstr|Miss|Dr)\s*)/g;
        var isDate = /(-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-)/g

        if (getTitle.test(a.value)) {                
            var aName = a.value, bName = b.value;
            return aName.replace(getTitle, '') < bName.replace(getTitle, '') ? -1 : 1
        }

        if (isDate.test(a.value)) {
            var aDate = new Date(a.value), bDate = new Date(b.value);
            return aDate.getTime() < bDate.getTime() ? -1 : 1
        }

        return a.index < b.index ? -1 : 1
    }

比较器基本上是一个类似于 javascript .sort() 方法的函数。

如果该值包含一个头衔(先生、夫人等),那么它就是一个名字,所以我会去掉这些头衔并比较实际的名字,而不考虑头衔。

如果变量匹配 -Month- 模式,它是一个日期字符串,我比较解析的日期对象。

希望这对某人有所帮助,我花了一段时间才弄清楚。如果您认为有更好的方法,我愿意接受建议,并随时为想要使用 AngularJS 的人发布答案 =

【讨论】:

    猜你喜欢
    • 2018-02-10
    • 2019-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-12
    相关资源
    最近更新 更多