diff options
| author | Julien Mougenot <jum@odoo.com> | 2019-12-19 10:30:08 +0000 |
|---|---|---|
| committer | Julien Mougenot <jum@odoo.com> | 2020-01-06 14:37:16 +0000 |
| commit | ab37648cb1c3a4ab7db23e3a8cdef87008d5d1e0 (patch) | |
| tree | 3d15d1f0d3a5748505bea713e5098b715f0119fe /addons/web/static/src/js | |
| parent | f2046910bd0649ce78285245f9b929224c4b06e7 (diff) | |
[ADD] web: useFocusOnUpdate hook
Added a new custom hooks: useFocusOnUpdate.
This hook returns a function taking a DOM selector as an argument.
That function will focus the first matching element on the next repaint of
the component.
Diffstat (limited to 'addons/web/static/src/js')
| -rw-r--r-- | addons/web/static/src/js/core/custom_hooks.js | 48 |
1 files changed, 43 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 d2dbdb14a44..695acfd1e61 100644 --- a/addons/web/static/src/js/core/custom_hooks.js +++ b/addons/web/static/src/js/core/custom_hooks.js @@ -2,8 +2,40 @@ odoo.define('web.custom_hooks', function (require) { "use strict"; const { Component, hooks } = owl; - const { onMounted, onWillUnmount } = hooks; + const { onMounted, onPatched, onWillUnmount } = hooks; + /** + * Returns a function which purpose is to focus the given selector on the next + * repaint (mount or patch). Its default selector is the first element having + * an `autofocus' attribute. Text selection will be set at the end of the value + * if the target is a text element. The action is lost if no element was found. + * + * @returns {Function} + */ + function useFocusOnUpdate() { + const component = Component.current; + component.__willFocus = null; + + function _focusSelector() { + if (component.__willFocus) { + const target = component.el.querySelector(component.__willFocus); + if (target) { + target.focus(); + if (['INPUT', 'TEXTAREA'].includes(target.tagName)) { + target.selectionStart = target.selectionEnd = target.value.length; + } + } + component.__willFocus = null; + } + } + + onMounted(_focusSelector); + onPatched(_focusSelector); + + return function focusOnUpdate(selector = '[autofocus]') { + component.__willFocus = selector; + }; + } /** * When component needs to listen to DOM Events on element(s) that is not part of his hierarchy, we can use @@ -17,15 +49,21 @@ odoo.define('web.custom_hooks', function (require) { * in the constructor of the OWL component that needs to be notified, * `useExternalListener(window, 'click', this._doSomething);` listen to the click event on window and call * `this._doSomething` function of the component when the click happened - * */ - function useExternalListener(target, eventName, handler) { + * + * @param {EventTarget} target + * @param {string} eventName + * @param {Function} handler + * @param {(Object|boolean)} [eventParams] + */ + function useExternalListener(target, eventName, handler, eventParams) { const boundHandler = handler.bind(Component.current); - onMounted(() => target.addEventListener(eventName, boundHandler)); - onWillUnmount(() => target.removeEventListener(eventName, boundHandler)); + onMounted(() => target.addEventListener(eventName, boundHandler, eventParams)); + onWillUnmount(() => target.removeEventListener(eventName, boundHandler, eventParams)); } return { + useFocusOnUpdate, useExternalListener, }; }); |
