Accessing #each data context in Template event

Say I have this scenario:

template1.html

...
{{#each thing in things}}
    {{thing.name}}
    <button name="doThing">Do thing with thing id</button>
{{/each}}
...

template1.js

Template.template1.events({
    'click button'(event, instance) {
         // instance refers to the entire template here, not the context within the #each loop
    }
});

If I want to attach events to each button do something that uses the thing id, how do I get that context? I know I can create another template and attach event handlers on that, but it’s a bit tedious to create new templates for each time I want to iterate

Switch your #each to something like:

...
{{#each things}}
  {{name}}
  <button>Do thing with thing id</button>
{{/each}}
...

Your event will then have access to the proper data context for each thing via this:

Template.template1.events({
  'click button'(event, instance) {
    const thingId = this._id;
    // Do something with thingId
  }
});

Another option is to add the id to the button

{{#each thing in things}}
    {{thing.name}}
    <button class="thing" name="doThing" id="{{thing._id}}">Do thing with thing id</button>
{{/each}}

and access the thing-id like so

Template.template1.events({
 'click button.thing': function(event, instance) {
   console.log(event.currentTarget.id);
 }
});

Thanks for responses. Not really a fan of either of these solutions (for the first I’m unhappy about losing the namespacing and the second I’m sometimes trying to encode an object which is a bit of a pain), but I’ll work with it.

2 Likes

Agree with aspin. None of the solutions seem elegant. Is there any real reason why #each in isn’t able to pass its data context into the event?

Anyone have an update on this? Tacking on data to the DOM just to be able to retrieve it in an event handler is inconvenient and repetitive.

I did find out that if you place the #each body in a separate <template></template>, then the event handler’s this will have that template’s context data, but that could end up with a lot of templates.

@nephets Did you try this:

@coagmano I actually ended up placing the #each body in a separate <template></template>, then the event handler’s this has that template’s context data. That works, but that could end up with a lot of unnecessary templates. Just seems like there should be a better solution than any of these workarounds!

The solution I linked does not mention a separate template, nor is it needed. Try without the template