流星:如何在模板中对结果进行分组?
Meteor: how to group results in template?
我有一个应用程序,用户可以在不同的日期时间签到。然后我的目标是显示谁在不同的日期在那里。
类似的东西:
11/05 : Mat, Lisa, Andrew
14/05 : Lisa
etc.
我看了一下 $groupby 聚合,但对于我的简单用法来说它似乎真的很重。
我也可以在 db.find().fetch() 上循环,但我觉得我会失去反应性。
我设法让它与一个简单的模板助手一起工作:
resultDate = null;
Template.result.helpers({
date: function(){
var date = moment(this.datetime).endOf("day").fromNow();
if(date == resultDate)
return false;
resultDate = date;
return date;
}
}
但如您所见,这并不是真正的经典方式,例如,如果我需要调用 {{date}} 两次,一切都会崩溃。
我已经寻找了几个小时的合适解决方案,但一无所获。有什么想法吗?
谢谢!
下面是一个示例,说明如何在不丢失反应性的情况下使用您的集合执行此客户端。
关键问题是将反应式数据源(集合)转换为对象数组,这些对象反映了所需的日期输出以及签到人员的姓名。
这个数组看起来像:
[
{date: '2015-05-11', names: ['Mat', 'Lisa', 'Andrew']},
{date: '2015-05-14', names: ['Lisa']},
]
我假设您的集合称为 Checkin,每个文档中有 2 个字段,date
和 name
。
您的集合是一个反应性数据源。您可以通过 observeChanges
获得有关集合更改的通知。
通过触发添加、更改和删除事件,您可以通过每天签到来重建阵列。这些事件都调用 rebuildCheckinPerDay
来构建实际的数组。
每次重建时,数组都会保存在 ReactiveVar checkinPerDateVar
中。而且因为 ReactiveVar 也是一个反应式数据源,模板助手 checkinPerDate
每次更改 reactiveVar 时都会得到 re运行。
构建数组是由几个underscorejs 函数完成的。首先,集合按日期排序并在数组中获取,然后按日期分组(时间被 .endOf('day')
删除),然后映射到最终结构。因为 _.groupBy
returns 项作为 {id, name, date} 你必须使用 _.pluck
来提取名称。
为了转换日期和方便的模板助手来格式化日期,我使用了 momentjs。实际上 运行 这个例子你必须包含包 momentjs:moment
和 reactive-var
。
在示例中显示了完整的日期。但如果您愿意,您可以轻松地将其转换为 moment(this.datetime).endOf("day").fromNow()
。
完整示例:
检查-in.html.
<template name="checkinPerDate">
{{#each checkinPerDate}}
<div>
{{formatDate date}} - {{names}}
</div>
{{/each}}
</template>
检查-in.js.
Template.registerHelper('formatDate', function(date) {
return moment(date).format('DD-MM-YYYY');
});
// Reactive variable to hold the array with names per check-in day
var checkinPerDateVar = new ReactiveVar([]);
// Build the array with check-ins per day that mirror the final view in the template
var rebuildCheckinPerDay = function() {
var checkinPerDateArray = _.map(
_.groupBy(Checkin.find({}, {sort: {date : 1}}).fetch(), function(item) {
return moment(item.date).endOf('day');
}), function(dateItem, date) {
return {date: date, names: _.pluck(dateItem, 'name')};
});
checkinPerDateVar.set(checkinPerDateArray);
}
Template.checkinPerDate.onCreated(function() {
this.subscribe('checkin', function() {
var cursor = Checkin.find();
var handle = cursor.observeChanges({
added: function (id, checkin) {
console.log('added ', id, JSON.stringify(checkin));
rebuildCheckinPerDay();
},
changed: function (id, checkin) {
console.log('changed ', id, JSON.stringify(checkin));
rebuildCheckinPerDay();
},
removed: function (id) {
console.log('removed ', id);
rebuildCheckinPerDay();
}
});
});
});
Template.checkinPerDate.helpers({
// This helper function is reactive because of the use of reactive variable checkinPerDateVar.
// It gets rerun each time the variable was changed
checkinPerDate: function () {
var checkinPerDateArray = checkinPerDateVar.get();
return checkinPerDateArray;
}
});
谢谢 Jos 的回答,但对于我来说,它看起来仍然很沉重,因为我的简单需求与 HTML 格式化比对象操作更相关。我认为您的回答非常适合对请求进行复杂处理,但就我而言,我只需要显示日期排序记录的日期,而无需在同一天重复。
所以,我制定了我最初的辅助函数,我想我找到了更好的方法来做到这一点:
var resultDateVar = [];
Template.result.helpers({
date: function(){
if(!resultDateVar[this._id]){
var date = moment(this.datetime).endOf("day").fromNow();
resultDateVar[this._id] = (resultDateVar.last == date)? false : date;
resultDateVar.last = date;
}
return resultDateVar[this._id]
}
});
希望对您有所帮助:)
我有一个应用程序,用户可以在不同的日期时间签到。然后我的目标是显示谁在不同的日期在那里。
类似的东西:
11/05 : Mat, Lisa, Andrew
14/05 : Lisa
etc.
我看了一下 $groupby 聚合,但对于我的简单用法来说它似乎真的很重。 我也可以在 db.find().fetch() 上循环,但我觉得我会失去反应性。
我设法让它与一个简单的模板助手一起工作:
resultDate = null;
Template.result.helpers({
date: function(){
var date = moment(this.datetime).endOf("day").fromNow();
if(date == resultDate)
return false;
resultDate = date;
return date;
}
}
但如您所见,这并不是真正的经典方式,例如,如果我需要调用 {{date}} 两次,一切都会崩溃。
我已经寻找了几个小时的合适解决方案,但一无所获。有什么想法吗?
谢谢!
下面是一个示例,说明如何在不丢失反应性的情况下使用您的集合执行此客户端。
关键问题是将反应式数据源(集合)转换为对象数组,这些对象反映了所需的日期输出以及签到人员的姓名。 这个数组看起来像:
[
{date: '2015-05-11', names: ['Mat', 'Lisa', 'Andrew']},
{date: '2015-05-14', names: ['Lisa']},
]
我假设您的集合称为 Checkin,每个文档中有 2 个字段,date
和 name
。
您的集合是一个反应性数据源。您可以通过 observeChanges
获得有关集合更改的通知。
通过触发添加、更改和删除事件,您可以通过每天签到来重建阵列。这些事件都调用 rebuildCheckinPerDay
来构建实际的数组。
每次重建时,数组都会保存在 ReactiveVar checkinPerDateVar
中。而且因为 ReactiveVar 也是一个反应式数据源,模板助手 checkinPerDate
每次更改 reactiveVar 时都会得到 re运行。
构建数组是由几个underscorejs 函数完成的。首先,集合按日期排序并在数组中获取,然后按日期分组(时间被 .endOf('day')
删除),然后映射到最终结构。因为 _.groupBy
returns 项作为 {id, name, date} 你必须使用 _.pluck
来提取名称。
为了转换日期和方便的模板助手来格式化日期,我使用了 momentjs。实际上 运行 这个例子你必须包含包 momentjs:moment
和 reactive-var
。
在示例中显示了完整的日期。但如果您愿意,您可以轻松地将其转换为 moment(this.datetime).endOf("day").fromNow()
。
完整示例:
检查-in.html.
<template name="checkinPerDate">
{{#each checkinPerDate}}
<div>
{{formatDate date}} - {{names}}
</div>
{{/each}}
</template>
检查-in.js.
Template.registerHelper('formatDate', function(date) {
return moment(date).format('DD-MM-YYYY');
});
// Reactive variable to hold the array with names per check-in day
var checkinPerDateVar = new ReactiveVar([]);
// Build the array with check-ins per day that mirror the final view in the template
var rebuildCheckinPerDay = function() {
var checkinPerDateArray = _.map(
_.groupBy(Checkin.find({}, {sort: {date : 1}}).fetch(), function(item) {
return moment(item.date).endOf('day');
}), function(dateItem, date) {
return {date: date, names: _.pluck(dateItem, 'name')};
});
checkinPerDateVar.set(checkinPerDateArray);
}
Template.checkinPerDate.onCreated(function() {
this.subscribe('checkin', function() {
var cursor = Checkin.find();
var handle = cursor.observeChanges({
added: function (id, checkin) {
console.log('added ', id, JSON.stringify(checkin));
rebuildCheckinPerDay();
},
changed: function (id, checkin) {
console.log('changed ', id, JSON.stringify(checkin));
rebuildCheckinPerDay();
},
removed: function (id) {
console.log('removed ', id);
rebuildCheckinPerDay();
}
});
});
});
Template.checkinPerDate.helpers({
// This helper function is reactive because of the use of reactive variable checkinPerDateVar.
// It gets rerun each time the variable was changed
checkinPerDate: function () {
var checkinPerDateArray = checkinPerDateVar.get();
return checkinPerDateArray;
}
});
谢谢 Jos 的回答,但对于我来说,它看起来仍然很沉重,因为我的简单需求与 HTML 格式化比对象操作更相关。我认为您的回答非常适合对请求进行复杂处理,但就我而言,我只需要显示日期排序记录的日期,而无需在同一天重复。
所以,我制定了我最初的辅助函数,我想我找到了更好的方法来做到这一点:
var resultDateVar = [];
Template.result.helpers({
date: function(){
if(!resultDateVar[this._id]){
var date = moment(this.datetime).endOf("day").fromNow();
resultDateVar[this._id] = (resultDateVar.last == date)? false : date;
resultDateVar.last = date;
}
return resultDateVar[this._id]
}
});
希望对您有所帮助:)