diff options
| author | Joseph Caburnay <jcb@odoo.com> | 2020-02-17 11:33:17 +0000 |
|---|---|---|
| committer | Pierre Masereel <pim@odoo.com> | 2020-02-20 12:33:54 +0000 |
| commit | 2c383aae48b81597d3dae6318a3e8a8f56f6f6b8 (patch) | |
| tree | e95c534ed1a6f8926a2a09d59c5f19a9a9f35c89 | |
| parent | 85f6290b68fdb01ed42b69e191b8aeb3689397b8 (diff) | |
[IMP] web: custom_hooks: useListener able to pass options to addEventListener
addEventListener supports an `options` argument, which can
be useful to listen on events during the capture phase
This commit allows to pass these options to the hook useListener
closes odoo/odoo#45478
Signed-off-by: pimodoo <pimodoo@users.noreply.github.com>
| -rw-r--r-- | addons/web/static/src/js/core/custom_hooks.js | 13 | ||||
| -rw-r--r-- | addons/web/static/tests/component_extension_tests.js | 67 |
2 files changed, 75 insertions, 5 deletions
diff --git a/addons/web/static/src/js/core/custom_hooks.js b/addons/web/static/src/js/core/custom_hooks.js index a99576b73ce..c196dd7f900 100644 --- a/addons/web/static/src/js/core/custom_hooks.js +++ b/addons/web/static/src/js/core/custom_hooks.js @@ -66,13 +66,16 @@ odoo.define('web.custom_hooks', function () { * @param {string} eventName the name of the event * @param {string} [querySelector] a JS native selector for event delegation * @param {function} handler the event handler (will be bound to the component) + * @param {Object} [addEventListenerOptions] to be passed to addEventListener as options. + * Useful for listening in the capture phase */ - function useListener(eventName, querySelector, handler) { - if (arguments.length === 2) { + function useListener(eventName, querySelector, handler, addEventListenerOptions) { + if (typeof arguments[1] !== 'string') { querySelector = null; handler = arguments[1]; + addEventListenerOptions = arguments[2]; } - if (!(typeof handler === 'function')) { + if (typeof handler !== 'function') { throw new Error('The handler must be a function'); } @@ -99,10 +102,10 @@ odoo.define('web.custom_hooks', function () { boundHandler = handler.bind(comp); } onMounted(function () { - comp.el.addEventListener(eventName, boundHandler); + comp.el.addEventListener(eventName, boundHandler, addEventListenerOptions); }); onWillUnmount(function () { - comp.el.removeEventListener(eventName, boundHandler); + comp.el.removeEventListener(eventName, boundHandler, addEventListenerOptions); }); } diff --git a/addons/web/static/tests/component_extension_tests.js b/addons/web/static/tests/component_extension_tests.js index f0b33db655c..08f5071ec04 100644 --- a/addons/web/static/tests/component_extension_tests.js +++ b/addons/web/static/tests/component_extension_tests.js @@ -181,5 +181,72 @@ odoo.define('web.component_extension_tests', function (require) { parent.destroy(); fixture.classList.remove('custom-class'); }); + + QUnit.test("useListener with capture option", async function (assert) { + assert.expect(7); + const fixture = document.body.querySelector('#qunit-fixture'); + + class Leaf extends Component { + constructor() { + super(); + useListener('custom1', this._onCustom1); + } + _onCustom1() { + assert.step(`${this.constructor.name} custom1`); + } + } + Leaf.template = xml`<div class="leaf"/>`; + + class Root extends Component { + constructor() { + super(); + useListener('custom1', this._onCustom1, { capture: true }); + } + _onCustom1(event) { + assert.step(`${this.constructor.name} custom1`); + const detail = event.detail; + if (detail && detail.stopMe) { + event.stopPropagation(); + } + } + } + Root.template = xml`<div class="root"><Leaf/></div>`; + Root.components = { Leaf }; + + const root = new Root(null); + await root.mount(fixture); + + const rootNode = document.body.querySelector('.root'); + const leafNode = document.body.querySelector('.leaf'); + rootNode.dispatchEvent(new CustomEvent('custom1', { + bubbles: true, + cancelable: true + })); + assert.verifySteps(['Root custom1']); + + // Dispatch custom1 on the leaf element. + // Since we listen in the capture phase, Root is first triggered. + // The event is stopped there. + leafNode.dispatchEvent(new CustomEvent('custom1', { + bubbles: true, + cancelable: true, + detail: { + stopMe: true + }, + })); + assert.verifySteps(['Root custom1']); + + // Same as before, except this time we don't stop the event + leafNode.dispatchEvent(new CustomEvent('custom1', { + bubbles: true, + cancelable: true, + detail: { + stopMe: false + } + })); + assert.verifySteps(['Root custom1', 'Leaf custom1']); + + root.destroy(); + }); }); }); |
