Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Meteor have a weird event handler syntax?

Something that has bothered me about Meteor is the way that events are attached to the templates. It's not so much a gripe about not being able to use jQuery, but I just can't suspend my suspicion that something is wrong with the way these are written.

Here's a condensed example:

Template.input.events = {
    'mousedown input#message' : function(event){
        console.log('the mouse was pressed');
    },

    'touchstart input#message' : function(event){
        console.log('a finger was pressed');
    },
}

Can anyone explain to me why the event name and the query selector would be combined into a single string like 'mousedown input#message'? I just don't understand why anyone would want to make something that worked this way.

If it were me, I would nest the events under each selector like so. Note: this code doesn't work, it's just how I think it should look.

Template.input.events = {
    'input#message' : {
        'mousedown' : function(event){
            console.log('the mouse was pressed');
        },

        'touchstart' : function(event){
            console.log('a finger was pressed');
        }
    }
}
like image 259
Wray Bowling Avatar asked Feb 14 '23 17:02

Wray Bowling


1 Answers

One reason is that you can use an event name without a selector to attach events to a template itself. One common use case for this is to attach a submit event handler to a template containing a form:

Template.someForm.events({
  "submit": function() {
    /*...*/
  }
});

Also, you can use a comma separated list to use the same handler function for multiple event types. This even allows you to use the same event handler for different types of events on entirely different elements. Maybe you want to create an event handler that fires when the user either clicks a save button or presses the "s" key with something focused in the template. Meteor's event system allows this to be defined in the event map with just one definition:

Template.someTemplate.events({
  "keyup, click .save": function(event, template) {
    if (event.type === "keyup" && event.which !== 83) return;

    // save
  }
});

In your case, I might just do this:

Template.input.events({
  "mousedown #message, touchstart #message" : function(event){
    // you can do different things by examining event.type
  }
});

However, despite the advantages of Meteor's event maps, it's easy to use your format if you want. Here's a function that takes an event map in your format and transforms it into a Meteor event map:

// Call it whatever you want
var transformEvents = function(selectorEvents) {
  return _.reduce(selectorEvents, function(meteorEvents, events, selector) {
    _.each(events, function(handler, eventType) {
      meteorEvents[eventType + " " + selector] = handler;
    });
    return meteorEvents;
  }, {});
};

Just pass your style of event map through this and it will turn it into a Meteor compatible one :)

As far as not being able to use jQuery, the reason for this is that Meteor's event system automatically scopes your event handlers to a template instance, which would be very difficult to do with jQuery alone. Technically I don't think there's anything stopping you from using jQuery events, but it would cause some major headaches that Meteor's event system avoids.

like image 117
sbking Avatar answered Feb 23 '23 17:02

sbking