andersryanc
andersryanc

Reputation: 979

How do you stop an ember action from triggering on it's child elements / how to access events in actions

I know you can add bubbles=false to actions to stop propagation to parent elements, but how do you stop an action from getting called on it's child elements?

I'm trying to create an overlay to my site, which has a transparent background overlay-bg, a close button and some overlay-content. Each of these elements should be clickable to hide the overlay. But whenever I click the popup (which is restricted to a width of 400px inside the overlay-content) or the form elements inside the popup, etc... the hide method is still being called. The other actions on my form, etc are also being called at the same time.

My initial thought, a way I've done this with jQuery, is to use the event to determine if the clicked element has a class on it like canClose, so that if a child element is clicked the function would return before completion... but I can seem to figure out how to access an event object from the action. I tried returning this as a parameter of the action, but that just returns the ember component itself and not the element that was clicked.

Component:

App.OverlayComponent = Ember.Component.extend({

    elementId: 'login-overlay',

    // ...

    actions: {

        // ...

        hide: function () {
            var view = this;
            view.set('showing', false);
            view.$().one(Ember.$.support.transition.end, function () {
                view.destroy();
            });
        }
    },

});

Template:

<div class="overlay-bg" {{action 'hide'}}></div>

<a href="#" class="close" {{action 'hide'}}>&times;</a>

<div class="overlay-content" {{action 'hide' this}}>
    <div class="popup">
        <h1>Login</h1>

        <form {{action 'login' on='submit'}}>
            <label for="username">Username</label>
            {{input value=username id="username" placeholder="Your email address" classNameBindings='usernameError:error'}}

            <label for="password">Password</label>
            {{input type="password" value=password id="password" placeholder="Password" classNameBindings='passwordError:error'}}

            <button class="btn btn-primary" {{action 'login'}}>Login</button>
            <p class="text-center forgot"><a href="#" {{action 'forgot'}}>Forgot Password?</a></p>
        </form>

        <hr>

        <p class="mb0 text-center"><a href="#" title="Login with Facebook" class="btn btn-primary facebook" {{action 'facebook'}}><i class="fa fa-facebook"></i> Login with Facebook</a></p>
    </div>
    <p class="text-center signup">Don't have an account? <a href="#" {{action 'signup'}}>Signup</a></p>
</div>

UPDATE:

Forgot to mention, I also tried adding e to my hide function and inside the handlebars helper in the template (hide: function (e) {} and {{action 'hide' event}}) but when I log e it's undefined.

Also, I'm using Ember 1.0.0... do I need to update to a newer version to get access to events in my actions?

Upvotes: 2

Views: 1386

Answers (1)

Patrick Fisher
Patrick Fisher

Reputation: 8063

I had this exact problem. I kept the action on the bg layer and removed it from the parent element, i.e.

<div class="overlay-bg" {{ action 'hide' }}></div>
<div class="overlay-content">...</div>

If you had the action on .overlay-content because it covers .overlay-bg, you may need

.overlay-content {
  pointer-events: none;
}

.overlay-content > * {
  pointer-events: all;
}

Upvotes: 2

Related Questions