最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How do I modify a template instance from an event handler in Meteor without Session? - Stack Overflow

programmeradmin4浏览0评论

I am trying to implement a hierarchy of expandable post ments like in e.g. Quora, so that the user can click a ment and see any replies.

To this end, I would like to keep track of whether each "ment" template instance is "expanded" or not, toggling the state in the event handler.

I could do this using a whole stack Session variables (i.e. one for each ment), but this seems clumsy since there are an arbitrary number of ments on any given page.

Below is a snippet of what I'm trying at the moment.

JS:

Templatement_item.events = {
    'click #ment-content': function( e, instance ) {
        this.expanded = true;  // also tried instance.data.expanded = true
    }
};

Templatement_item.helpers({
    showChildComments: function(){
      this.expanded;
    }
});

HTML:

<template name="ment_item">
  <li class="ment ment-displayed" id="{{_id}}">
   <div class="ment-body">
      <div id="ment-content">
        <!-- some ment data here -->
      </div>
      {{#if showChildComments}}
      <ul class="ment-children ment-list">
          {{#each child_ments}}
            {{> ment_item}}
          {{/each}}
      </ul>
      {{/if}}
    </div>
  </li>
</template>

Unfortunately, when I step through, it seems that in the showChildComments helper, the template instance can't see the expanded variable. I did notice in the docs it says instance.data is read only in the events map.

Is there any way to modify the template instance within the event map directly?

I am trying to implement a hierarchy of expandable post ments like in e.g. Quora, so that the user can click a ment and see any replies.

To this end, I would like to keep track of whether each "ment" template instance is "expanded" or not, toggling the state in the event handler.

I could do this using a whole stack Session variables (i.e. one for each ment), but this seems clumsy since there are an arbitrary number of ments on any given page.

Below is a snippet of what I'm trying at the moment.

JS:

Template.ment_item.events = {
    'click #ment-content': function( e, instance ) {
        this.expanded = true;  // also tried instance.data.expanded = true
    }
};

Template.ment_item.helpers({
    showChildComments: function(){
      this.expanded;
    }
});

HTML:

<template name="ment_item">
  <li class="ment ment-displayed" id="{{_id}}">
   <div class="ment-body">
      <div id="ment-content">
        <!-- some ment data here -->
      </div>
      {{#if showChildComments}}
      <ul class="ment-children ment-list">
          {{#each child_ments}}
            {{> ment_item}}
          {{/each}}
      </ul>
      {{/if}}
    </div>
  </li>
</template>

Unfortunately, when I step through, it seems that in the showChildComments helper, the template instance can't see the expanded variable. I did notice in the docs it says instance.data is read only in the events map.

Is there any way to modify the template instance within the event map directly?

Share Improve this question asked Mar 29, 2013 at 6:43 francisbyrnefrancisbyrne 1871 silver badge8 bronze badges 1
  • Whats wrong with Session? You can also use JQuery in a more traditional way to go straight to the DOM the way quora does – Tarang Commented Mar 29, 2013 at 14:06
Add a ment  | 

2 Answers 2

Reset to default 10

You can create properties for a template instance inside of it's created event handler. And you can access the template instance as the second argument of the event map function.

Template.ment_item.created = function() {
  this.showChildren = false;
};

Template.ment_item.events({
  'click .ment-content': function(event, template) {
    template.showChildren = true;
  }
});

HOWEVER:

  1. you cannot access your template instance and its properties from within a template helper.
  2. Your template helper needs to be given a "reactive" data source anyways for it to change on the spot.
  3. Even if you go through the trouble of creating your own reactive data source, your approach to this feature will still create X amount of variables for X amount of ments on the page. That seems like an awful lot of variables to have in memory to implement one feature.

What I would suggest that you do instead is simplify your template to this:

<template name="ment_item">
  <li class="ment ment-displayed" id="{{_id}}">
   <div class="ment-body">
      <div class="ment-content">  <!-- changed this to a class -->
        <!-- some ment data here -->
      </div>
    </div>
  </li>
</template>

And then programmatically add the child ments to the ment-body in your event-handler. Keep in mind the following from the Meteor documentation:

A template that you declare as <template name="foo"> ... </template> can be accessed as the function Template.foo, which returns a string of HTML when called.

Oh, and you pass context to a template function as a JSON object. E.g.:

var context = {_id: ment_id, text: "Comment text!"};
Template.ment_item(context);

Update:

Meteor now gives you access to template instances from within a helper, using Template.instance(). In fact, it's a great way to increase the reusability of your template.

The example source below is from this article, authored by David Burles of Percolate Studio.

Template.hello.created = function () {
  // counter starts at 0
  this.state = new ReactiveDict();
  this.state.set('counter', 0);
}; 

Template.hello.helpers({
  counter: function () {
    return Template.instance().state.get('counter');
  }
});

Template.hello.events({
  'click button': function (event, template) {
    // increment the counter when button is clicked
    template.state.set('counter', template.state.get('counter') + 1);
  }
});

The article does a great job of illustrating why you would want this approach.

The advantage of storing information in the template instance is that you can make templates increasingly modular and decreasingly dependent on the place they are used.

发布评论

评论列表(0)

  1. 暂无评论