在Meteor框架中操作模板实例的正确方法是什么?

时间:2012-12-25 22:54:18

标签: meteor

我是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中,而不是之前(包含所有餐馆的所有菜单项,并且由于db中的这些项目数量很大,因此只能隐藏这些div)。

如果您认为我应该以其他方式处理解决方案,请告诉我,谢谢!

2 个答案:

答案 0 :(得分:4)

您应该使用{{#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);
  }
});

修改为了清楚起见,我创建了a complete example,您可以将其复制到项目中并试用。

答案 1 :(得分:1)

我几乎总是避免使用Session。我认为它污染了全球范围。它还会阻止您运行模板的多个实例。我建议使用作为模板实例范围的reactiveVar或reactiveDict。感谢Rahul开始一个演示项目。我拿了他的例子并对其进行了修改以显示我推荐的方法。

将reactiveDict附加到模板实例onCreate上。使用它来存储状态而不是全局Session var!

Template.Restaurants.onCreated(function() {
  this.state = new ReactiveDict;
  this.state.set('currentRestaurant', null); // could set a init value here
});

此事件处理程序将在click

上设置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);
},

菜单模板从数据上下文而不是从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

应用程序托管在meteor.com上 http://scopedreactitivydemo.meteor.com/