What is the proper way to manipulate template instance in Meteor framework?

前端 未结 2 1908
Happy的楠姐
Happy的楠姐 2021-01-15 13:14

I am new to Meteor and wondering how to solve what seems to me is a common problem.

Let\'s say I have a handlebars template listing restaurants:

<         


        
相关标签:
2条回答
  • 2021-01-15 13:16

    You should use {{#if}} and Session. Like this:

    <template name="Restaurants">
      {{#each Restaurant}}
        {{name}} 
        {{#if restaurantSelected}}
          {{> menuItems}}
        {{/if}}
      {{/each}}
    </template>
    

    By using Session, a reactive data source, you can set a global flag indicating whether a restaurant is selected.

    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);
    }
    

    Whenever you change that session key, the value will update and the template will be redrawn. So, you can toggle it when clicking a restaurant:

    Template.Restaurants.events({
      'click' : function (e) {
        // store the current restaurant ID
        // make sure the event selector is correct!
        Session.set("restaurantSelected", this._id);
      }
    });
    

    Edit For clarity's sake I created a complete example that you can copy into your project and try out.

    0 讨论(0)
  • 2021-01-15 13:38

    I almost always avoid Session. I think it pollutes the global scope. Also it prevents you from running multiple instances of the template. I recommend using a reactiveVar or reactiveDict scoped to the template instance. Thanks to Rahul for starting a demo project. I took his example and modified it to show my recommended approach.

    attach a reactiveDict to the template instance onCreate. Use this to store state instead of global Session var!

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

    this event handler will set the state of the reactiveDict on click

    'click': function(e, t) {
        t.state.set('currentRestaurant', this._id);
    }
    

    this helper is used to show/hide the menu template

    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 template receives the selected id from data context instead of from Session

    <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>
    

    added this helper just to show we really got the id

    Template.menuItems.helpers({
      restaurantName: function() {
        var restaurantMenu = Restaurants.findOne(this.restaurant);
        return restaurantMenu.name;
      },
    })
    

    Posted a fully working project to github. https://github.com/white-rabbit-japan/scopedReactivityDemo

    App is hosted on meteor.com http://scopedreactitivydemo.meteor.com/

    0 讨论(0)
提交回复
热议问题