我是 Meteor 的新手,想知道如何解决在我看来是一个常见问题。
假设我有一个列出餐厅的车把模板:
<template name="Restaurants">
{{#each Restaurant}}
{{name}}
{{/each}}
</template>
现在,当用户点击餐厅模板时,我想显示该餐厅的菜单。
我添加了一个名为“menuItems”的子模板,其中包含给定餐厅的所有菜单项:
<template name="Restaurants">
{{#each Restaurant}}
{{name}}
{{> menuItems}}
{{/each}}
</template>
我只想在用户单击餐厅模板上的任意位置时呈现 menuItems 子模板的一个实例(只呈现所选餐厅的菜单项)。
应该是这样的:
Template.Restaurants.events({
'click' : function (e) {
// This is where I need help - what's the right way to display only one subtemplate instance?
}
});
我的问题是——我如何才能选择和显示正确的 menuItems 模板实例?
我还想仅在单击之后而不是之前将 menuItems 模板实例放置在 DOM 中(拥有所有餐厅的所有菜单项并且仅隐藏那些 div 不是一个选项,因为数据库中的这些项目数量很多)。
如果您认为我应该以其他方式解决问题,请告诉我,谢谢!
你应该使用
{{#if}}
和Session
。像这样:
<template name="Restaurants">
{{#each Restaurant}}
{{name}}
{{#if restaurantSelected}}
{{> menuItems}}
{{/if}}
{{/each}}
</template>
通过使用响应式数据源
Session
,您可以设置一个全局标志,指示是否选择了一家餐厅。
Template.Restaurants.restaurantSelected = function() {
// check whether this restaurant is selected. "this" refers to the current
// context, eg. the current restaurant in the loop
return Session.equals("restaurantSelected", this._id);
}
每当您更改该会话密钥时,该值将更新并且模板将被重新绘制。因此,您可以在单击餐厅时切换它:
Template.Restaurants.events({
'click' : function (e) {
// store the current restaurant ID
// make sure the event selector is correct!
Session.set("restaurantSelected", this._id);
}
});
编辑为了清楚起见,我创建了一个完整的示例,您可以将其复制到您的项目中并试用。
我几乎总是避免使用 Session。我认为它污染了全球范围。它还会阻止您运行模板的多个实例。我建议使用作用域为模板实例的 reactiveVar 或 reactiveDict。感谢 Rahul 启动了一个演示项目。我以他的例子为例并对其进行了修改以展示我推荐的方法。
将 reactiveDict 附加到模板实例 onCreate。使用它来存储状态而不是全局会话变量!
Template.Restaurants.onCreated(function() {
this.state = new ReactiveDict;
this.state.set('currentRestaurant', null); // could set a init value here
});
此事件处理程序将在单击时设置 reactiveDict 的状态
'click': function(e, t) {
t.state.set('currentRestaurant', this._id);
}
这个助手用于显示/隐藏菜单模板
currentRestaurant: function() {
// check whether this restaurant is selected. "this" refers to the current
// context, eg. the current restaurant in the loop
return Template.instance().state.equals("currentRestaurant", this._id);
},
menu 模板从数据上下文而不是从 Session 接收选定的 id
<template name="Restaurants">
<ul>
{{#each Restaurant}}
<li>
{{name}}
{{#if currentRestaurant}}
{{> menuItems restaurant=_id}}
{{/if}}
</li>
{{/each}}
</ul>
</template>
<template name="menuItems">
<ul>
<li class="menu">I'm a menu for {{restaurantName}}!</li>
</ul>
</template>
添加这个助手只是为了表明我们真的得到了 id
Template.menuItems.helpers({
restaurantName: function() {
var restaurantMenu = Restaurants.findOne(this.restaurant);
return restaurantMenu.name;
},
})
向 github 发布了一个完整的工作项目。 https://github.com/white-rabbit-japan/scopedReactivityDemo
App 托管在 meteor.com 上 http://scopedreactitivydemo.meteor.com/
最后,回答评论里的一个问题
Meteor.call('updateDoc', docId, newData, (error, result) => {
if (error) {
// Handle the error
} else {
// Set the editProductId value in editState using the result from
the method
editState.set('editProductId', result);
}
});