Charles
Charles

Reputation: 11778

EmberJS - How not to conflict with actions and events in components

I think there is a an issue between template actions and events in components.

As far as I understand all action clicks will be first executed and bubbled. Finally events in components will be also executed. There are like two parallel stacks executed one after the other.

If you have something like this in the template of a component:

Hello <button onclick={{action 'clickMe'}}>Click me</button>

and this in the corresponding javascript file:

click: function() {
   alert('second message');
}

You are not sure that the second message will be displayed. If event.stopPropagation() is called in the stack of action (not necessary inside the action 'clickMe'), the second message won't be shown.

Here is a twiddle: https://ember-twiddle.com/c9a014a0c19851596d5e1184c9967cbc

Is there a solution to bypass this problem?

Upvotes: 1

Views: 348

Answers (2)

Ember Freak
Ember Freak

Reputation: 12872

When you say, <button onclick={{action 'clickMe'}}>Click me</button> - its nothing to do with ember, its just normal function registered for the click event.

When you say, <button {{action 'clickMe'}}>Click me</button> here Ember will take control(I am not sure what I am talking about, but generally speaking event processing will be handled by Ember).

twiddle1 - Ember is handling the all the event handling(ie.,<div {{action 'test'}}> then you can expect, event propagating from child component

output:

action click from my-child
click from my-child
action click from my-parent
click event from my-parent

Neat and this is the expected behaviour. Even though you call event.stopPropagation parent component, it's not doing anything.

twiddle 2 - Browser is handling the event, ie., <div onclick={{action 'test'}}>

output:

action click from my-child
action click from my-parent
click from my-child
click event from my-parent

Here you can first its triggering action click from child to parent and then calling click handler for the corresponding component. In this case, if you call event.stopPropagation() in parent action click handler, then ember will not have an opportunity to call click handler of parent/child component.

This is what you are experiencing, to resolve you can move from <div onclick={{action 'clickMe'}}> to <div {{action 'clickMe'}}>.

Upvotes: 1

feanor07
feanor07

Reputation: 3368

I would oppose the suggestion made by @kumkanillam in his answer: " to resolve you can move from <div onclick={{action 'clickMe'}}> to <div {{action 'clickMe'}}>."

The first one (the original one you have used in your question) is the ember's closure action in action :) It is much more powerful; such that you can return values from the parent component to the child component; because it is in fact a function where this context is properly set by ember underneath and you can detect unhandled actions eagerly. On the other hand what is suggested by @kumkanillam is generally named "action in element space". It is low level DOM event handling by Ember.

Please take a look at the following excellent article that explains why closure actions rock! Regarding your question; what I would suggest is using closure actions as much as possible and avoid DOM event action handling via moving the relevant code part to the action handling as @DanielKmak already mentioned in his comment. I personally prefer closure actions as much as possible and only rely on DOM event handlers (such as click within box-content and my-component in your twiddle) when it is inevitable.

Upvotes: 2

Related Questions