diff --git a/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js b/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js index 6de7ff99412..50bad97f7da 100644 --- a/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js +++ b/packages/@ember/-internals/glimmer/tests/integration/helpers/element-action-test.js @@ -712,6 +712,45 @@ moduleFor( this.assert.equal(originalHandlerWasCalled, true, 'the click handler was called'); } + ['@test multiple actions with bubbles=false for same event are called but prevent bubbling']() { + let clickAction1WasCalled = false; + let clickAction2WasCalled = false; + let eventHandlerWasCalled = false; + + let ExampleComponent = Component.extend({ + actions: { + clicked1() { + clickAction1WasCalled = true; + }, + clicked2() { + clickAction2WasCalled = true; + }, + }, + }); + + this.registerComponent('example-component', { + ComponentClass: ExampleComponent, + template: strip` + click me`, + click() { + eventHandlerWasCalled = true; + }, + }); + + this.render('{{example-component}}'); + + runTask(() => { + this.$('a').trigger('click'); + }); + + this.assert.ok(clickAction1WasCalled, 'the first clicked action was called'); + this.assert.ok(clickAction2WasCalled, 'the second clicked action was called'); + this.assert.notOk(eventHandlerWasCalled, 'event did not bubble up'); + } + ['@test it should work properly in an #each block']() { let editHandlerWasCalled = false; @@ -1359,6 +1398,40 @@ moduleFor( this.assert.ok(doubleClickActionWasCalled, 'the doubleClicked action was called'); } + ['@test allows multiple actions for same event on a single element']() { + let clickAction1WasCalled = false; + let clickAction2WasCalled = false; + + let ExampleComponent = Component.extend({ + actions: { + clicked1() { + clickAction1WasCalled = true; + }, + clicked2() { + clickAction2WasCalled = true; + }, + }, + }); + + this.registerComponent('example-component', { + ComponentClass: ExampleComponent, + template: strip` + click me`, + }); + + this.render('{{example-component}}'); + + runTask(() => { + this.$('a').trigger('click'); + }); + + this.assert.ok(clickAction1WasCalled, 'the first clicked action was called'); + this.assert.ok(clickAction2WasCalled, 'the second clicked action was called'); + } + ['@test it should respect preventDefault option if provided']() { let ExampleComponent = Component.extend({ actions: { diff --git a/packages/@ember/-internals/views/lib/system/event_dispatcher.js b/packages/@ember/-internals/views/lib/system/event_dispatcher.js index 3af4a24536b..4070a52cdbd 100644 --- a/packages/@ember/-internals/views/lib/system/event_dispatcher.js +++ b/packages/@ember/-internals/views/lib/system/event_dispatcher.js @@ -285,13 +285,16 @@ export default EmberObject.extend({ return; } + let result = true; for (let index = 0; index < actions.length; index++) { let action = actions[index]; if (action && action.eventName === eventName) { - return action.handler(event); + // return false if any of the action handlers returns false + result = action.handler(event) && result; } } + return result; }; // Special handling of events that don't bubble (event delegation does not work).