summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorJulien Mougenot <jum@odoo.com>2019-12-19 10:30:08 +0000
committerJulien Mougenot <jum@odoo.com>2020-01-06 14:37:16 +0000
commitab37648cb1c3a4ab7db23e3a8cdef87008d5d1e0 (patch)
tree3d15d1f0d3a5748505bea713e5098b715f0119fe /addons/web/static/src
parentf2046910bd0649ce78285245f9b929224c4b06e7 (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')
-rw-r--r--addons/web/static/src/js/core/custom_hooks.js48
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,
};
});