A quick question on the context of the event handlers for templates in Meteor (with Handlebars).
Well, this is only partially true. Let's use an example from the docs:
<template name="scores">
{{#each player}}
{{> playerScore}}
{{/each}}
</template>
<template name="playerScore">
<div>{{name}}: {{score}}
<span class="givePoints">Give points</span>
</div>
</template
Template.playerScore.events({
'click .givePoints': function () {
Users.update({_id: this._id}, {$inc: {score: 2}});
});
Here the "this" context of the 'click .givePoints' event handler is indeed the template instance of playerScore. Let's modify the html:
<template name="scores">
<span class="click-me">Y U NO click me?<span>
{{#each player}}
{{> playerScore}}
{{/each}}
</template>
<template name="playerScore">
<div>{{name}}: {{score}}
<span class="givePoints">Give points</span>
</div>
</template>
... and add an event handler for .click-me on the scores template:
Template.scores.events({
'click .click-me': function () {
console.log(this);
}
});
Now, if you click the span, what do you get logged? The Window object! What did I expect to get? The template object! Or maybe the data context, but it's neither. However, inside the callbacks (e.g. Template.scores.rendered = function(){ ... }) the context of "this" is always the template instance.
I guess my real question would be: is this something to do with
Thanks!
This video explains the concepts:
http://www.eventedmind.com/posts/meteor-spark-data-annotation-and-data-contexts.
The direct answer to your question:
The thisArg inside an event handler should point to a data context. But sometimes the data context is undefined
. When you use the Function.prototype.call(thisArg, ...)
in JavaScript, if the thisArg is undefined (e.g. a dataContext is undefined) the browser will set this
equal to window. So, the docs aren't wrong per se but the event handling code isn't guarding against the possibility of a data context being undefined. I'm guessing that will be fixed in short order.
So, what produces a data context for a template? Normally your root template won't even have a data context. In other words, the Template function is called without an object. But if you use the {{#with
block helper or the {{#each
iterator, a data context will be created for each item in the list, or in the case of the with helper, the object.
Example:
var context = {};
<template name="withHelper">
{{#with context}}
// data context is the context object
{{/with}}
</template>
var list = [ {name: "one"}, {name: "two"} ];
<template name="list">
{{#each list}}
{{ > listItem }} // data context set to the list item object
{{/each}}
</template>
The first parameter in the function is the event. So you could use the target of the event to grab your element.
Template.scores.events({
'click .click-me': function (event, template) {
console.log(event.target);
$(event.target).text("O but I did!");
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With