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

问题描述 投票:0回答:2

我是 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 不是一个选项,因为数据库中的这些项目数量很多)。

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

meteor
2个回答
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);
  }
});

编辑为了清楚起见,我创建了一个完整的示例,您可以将其复制到您的项目中并试用。


1
投票

我几乎总是避免使用 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);
}

});

© www.soinside.com 2019 - 2024. All rights reserved.