Original: I have a table generated with ng-repeat with hundreds of entries consisting of several different unix timestamps. I'm using moment.js to make them display like "19 minutes ago" or however long ago it was. How would I have these update every five minutes, for example, without having to refresh the entire table (which takes a few seconds and will interrupt the user's sorting and selections).
原始:我有一个用ng-repeat生成的表,其中包含数百个不同的unix时间戳。我使用的时刻。让他们像“19分钟前”那样展示,或者是很久以前。例如,我如何每5分钟更新一次,而不需要刷新整个表(这需要几秒钟,会中断用户的排序和选择)。
14
I use the following filter. Filter updates value every 60 seconds.
我使用下面的过滤器。过滤器每60秒更新一次值。
angular
.module('myApp')
.filter('timeAgo', ['$interval', function ($interval){
// trigger digest every 60 seconds
$interval(function (){}, 60000);
function fromNowFilter(time){
return moment(time).fromNow();
}
fromNowFilter.$stateful = true;
return fromNowFilter;
}]);
And in html
在html
<span>{{ myObject.created | timeAgo }}</span>
13
I believe filters are evaluated every digest cycle, so using a filter to display your "time ago" strings might get CPU-expensive with hundreds of entries.
我认为每个摘要周期都会对过滤器进行评估,因此使用过滤器来显示“以前的时间”字符串可能会使cpu变得昂贵,因为有数百个条目。
I decided to go with a pubsub architecture, using essentially eburley's suggested approach (mainly because I don't have to watch for $destroy
events and manually unsubscribe), but with a NotificationService rather than a "Channel" function:
我决定采用pubsub架构,使用了eburley的建议方法(主要是因为我不需要查看$destroy事件和手动取消订阅),而是使用NotificationService而不是“Channel”功能:
.factory('NotificationService', ['$rootScope',
function($rootScope) {
// events:
var TIME_AGO_TICK = "e:timeAgo";
var timeAgoTick = function() {
$rootScope.$broadcast(TIME_AGO_TICK);
}
// every minute, publish/$broadcast a TIME_AGO_TICK event
setInterval(function() {
timeAgoTick();
$rootScope.$apply();
}, 1000 * 60);
return {
// publish
timeAgoTick: timeAgoTick,
// subscribe
onTimeAgo: function($scope, handler) {
$scope.$on(TIME_AGO_TICK, function() {
handler();
});
}
};
}])
A time-ago
directive registers/subscribes a timestamp (post.dt
in example HTML below) with the NotificationService:
time-ago指令注册/订阅一个时间戳(post)。用NotificationService:
<span time-ago="post.dt" class="time-ago"></span>
.directive('timeAgo', ['NotificationService',
function(NotificationService) {
return {
template: '<span>{{timeAgo}}</span>',
replace: true,
link: function(scope, element, attrs) {
var updateTime = function() {
scope.timeAgo = moment(scope.$eval(attrs.timeAgo)).fromNow();
}
NotificationService.onTimeAgo(scope, updateTime); // subscribe
updateTime();
}
}
}])
A few comments:
一些评论:
timeAgo
property to the scope, in my usage, this is okay, since I only seem to use the time-ago
directive inside an ng-repeat, so I'm just adding that property to the child scopes created by ng-repeat.{{timeAgo}}
will be examined every digest cycle, but this should be faster than running a filtertimeAgoTick()
could be made private, since likely only the NotificationService will need to publish the time ago event.4
Use angular's $timeout
service (just a wrapper around setTimeout()
) to update your data. Note the third parameter which indicates Angular should run a $digest
cycle that will update your data bindings.
使用角的$timeout服务(只是一个环绕setTimeout()的包装器)来更新您的数据。注意,第三个参数指出,角应该运行一个$digest循环,该循环将更新数据绑定。
Here's an example: http://jsfiddle.net/jandersen/vfpDR/
(This example updates every second so you don't have to wait 5 min to see it ;-)
这里有一个例子:http://jsfiddle.net/jandersen/vfpDR/
0
I ended up having $scope.apply() be called every five minutes by setInterval which reapplies the filters formatting the timestamps into "x minutes ago". Maybe a bit hacky but it works. I'm certain it isn't the optimal solution.
我最后拥有$scope.apply()每隔5分钟调用一次,它将把时间戳格式化为“x分钟前”。也许有点陈腐,但确实有效。我肯定这不是最优解。
0
I made a wrapper for momentjs https://github.com/jcamelis/angular-moment
我为momentjs https://github.com/jcamelis/angular-moment做了一个包装
<p moment-interval="5000">{{"2014-05-21T14:25:00Z" | momentFromNow}}</p>
I hope it works for you.
我希望它对你有用。
本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2013/08/01/4ca8766b4e2eb6dc6e757239ce0a0a35.html。