Can event.preventDefault() be removed from the {{action}} helper?


#1

I’m trying to figure out what the call to event.preventDefault() is used for in the {{action}} helper. It occurs on this line in the source.

This recently bit me when trying to set up a checkbox within a wrapper with an {{action}}. I found a hacky work-around that got me past the issue (though I did bring it up on Github), but it’s back with a vengence. I now find it’s preventing clicks on a label from propagating to the associated input, and my hacky work-around doesn’t apply since the labels aren’t Ember Views (and I’d rather keep it that way).

Commenting out the line with event.preventDefault() resolves my issues, but I’m wondering if there is something deeper at work that I’m missing. In the grand scheme of Ember.js, what purpose does this call perform? Can it be removed without causing unintended side effects?


#2

The idea is that there is a concept of event-firing/handling that in some cases can be initiated by a DOM events (clicking, mouseover, etc), but can also be fired just from the logic in your code, e.g. a view can call controller.send('actionName') and the controller can either handle that, or if it defines no such handler name, the event will forward to the router and be handled by that. Obviously in these cases, there’s no concept of calling preventDefault on a jQuery/DOM event. The {{action}} is basically a convenience to translate DOM/jQuery events into these more standardized application events that your app can understand and handle in a variety of ways.

If you need access to the jQuery/DOM event, you can define event handlers in a view subclass of Ember.Checkbox, e.g.

App.MyCheckbox = Ember.Checkbox.extend({
  click: function(event) {
    // event.preventDefault()
    this.get('controller').send('actionName');
  }
});

This will let you control whether the DOM/jQuery event continues to bubble.

This pattern of generating controller/router events from a view is common enough that Ember has a TargetActionSupport mixin, and, specifically for views, ViewTargetActionSupport, which is useful for simplifying some of the otherwise ugly syntax for firing events on controllers. So you would be able to do this:

App.MyCheckbox = Ember.Checkbox.extend(Ember.ViewTargetActionSupport, {
  action: 'actionName',
  click: function(event) {
    // event.preventDefault()
    this.triggerAction();
  }
});

Check this out for more info


#3

Thanks for taking the time to write this up, @machty! It helped a ton in actually understanding what the {{action}} helper does. I’ve refactored my code to resolve the issue without modification to ember. It’s good to be doing things the right way. :smiley: