AngularJS orderby 精炼

AngularJS orderby refining

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

我目前正在使用

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

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

这里的最佳做法是什么?

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

编辑编辑: AngularJS1.5.6

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

头衔和姓名

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

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

日期

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

objDate.getTime() //returns epoch in milliseconds

排序

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

ng-initw。 ng-flagged 属性

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

所以换句话说,你的 object 是从这个开始的:

{ 
    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

码笔

我用代码笔做了一个样本,但我用我的模板做的,模板是 coffeescript 和 jade。你大概能猜到我在做什么。

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

Ok, after some research, I found that the easiest solution is upgrading to AngularJS version 1.5.7 which introduces the comparator into the orderBy filter.

So I've changed my repeater to use an order by comparator

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

Variable is a string which I bound to the table headings so you can change the order by key, TrueOrFalse is a boolean which alternates between ascending and descending if you click the table heading and bookingComparator is my actual comparator.

My booking comparator looks like this

   $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
    }

The comparator is basically a function acting like the javascript .sort() method.

If the value contains a title (Mr, Mrs, etc) it is a name so I strip the titles and compare the actual names regardless of title.

If the variable matches a -Month- pattern, it's a date string and I compare the parsed date objects.

Hope this is helpful to someone, took me a while to figure out. I'm open to suggestions if you think there's a better way of doing this, and feel free to post an answer for people who want to use AngularJS =< 1.5.6