Reputation: 801
I have a problem which I don't know is related to the meteor implementation of events or to Javascript events in general.
I have a textbox attached to a "change" event. Next to it, I have a button attached to a "click" event.
When I do a change in the textbox and click the button, the click event does not fire (only the change event does). So I have to click the button two times for the click event to fire.
In Firefox, it works if I attach a mousedown
event instead of the click event to the button. In Chrome it doesn't work either ways.
Minimal code reproducing the problem:
JAVASCRIPT: testevent.js
if (Meteor.isClient) {
Session.set("something", "something");
Template.hello.foo = function() {
return Session.get("foo");
};
Template.hello.something = function() {
return Session.get("something");
}
Template.hello.events({
'click .buttonid' : function () {
console.log("click !");
},
'change .textid' : function (e,t) {
console.log("change !");
var bar = e.target.value;
Session.set("foo",bar);
}
});
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
HTML: testevent.html
<head>
<title>testevent</title>
</head>
<body>
{{> hello}}
</body>
<template name="hello">
<input type="text" class="textid" value="{{foo}}"/>
<input type="button" class="buttonid" value="{{something}}" />
</template>
When I replace class with id the click event fire, but when I have multiple fields with the same id the events work only on one field.
Upvotes: 0
Views: 3034
Reputation: 64312
The issue has to do with the hello.foo
:
Template.hello.foo = function() {
return Session.get("foo");
};
and the fact that the value of foo
is used to reactively populate the text input. If you remove the hello.foo
function everything works as expected. When the user clicks the button, the change event fires which sets the "foo"
session variable which in turn causes the template to re-render. I think the rendering process clears the remaining event queue, so the click handler never fires.
There are a couple of ways you can fix this. An easy (but crude) way is just to delay setting the session variable in the change event handler. For example:
Meteor.setTimeout(function(){Session.set("foo", bar);}, 100);
Obviously you would need to choose an appropriate delay and that may be browser/data dependent. Alternatively, you can just put the text input in its own template. For example:
<template name="hello">
{{> helloText}}
<input type="button" class="buttonid" value="{{something}}" />
</template>
<template name="helloText">
<input type="text" class="textid" value="{{foo}}"/>
</template>
After binding the events properly to this new template, you will find that helloText
will be rendered separately from hello
and thus your events will be preserved.
Upvotes: 1