From d6946775a2ca1be2065f7c6851f57a85f13ab2dc Mon Sep 17 00:00:00 2001 From: "Michael (mcm)" Date: Fri, 25 Feb 2022 08:59:01 +0000 Subject: [PATCH] [IMP] web: introduce LegacyComponent This commit introduces LegacyComponent and removes patches on Component. LegacyComponent is used instead of Component when the component uses features from owl 1 like getting its `el` or `trigger` an event. Part-of: odoo/odoo#85389 --- addons/web/__manifest__.py | 1 + .../src/legacy/js/component_extension.js | 37 +------ .../web/static/src/legacy/legacy_component.js | 97 +++++++++++++++++++ .../src/owl2_compatibility/component.js | 43 -------- 4 files changed, 99 insertions(+), 79 deletions(-) create mode 100644 addons/web/static/src/legacy/legacy_component.js delete mode 100644 addons/web/static/src/owl2_compatibility/component.js diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py index 74d3afefdf9..c17954fae4e 100644 --- a/addons/web/__manifest__.py +++ b/addons/web/__manifest__.py @@ -361,6 +361,7 @@ This module provides the core of the Odoo Web Client. 'web/static/lib/owl/owl.js', 'web/static/src/owl2_compatibility/*.js', 'web/static/src/legacy/js/component_extension.js', + 'web/static/src/legacy/legacy_component.js', 'web/static/lib/jquery/jquery.js', 'web/static/lib/jquery.ui/jquery-ui.js', 'web/static/lib/jquery/jquery.browser.js', diff --git a/addons/web/static/src/legacy/js/component_extension.js b/addons/web/static/src/legacy/js/component_extension.js index b1b18863e27..3eb4edffac0 100644 --- a/addons/web/static/src/legacy/js/component_extension.js +++ b/addons/web/static/src/legacy/js/component_extension.js @@ -1,45 +1,10 @@ (function () { - const { Component } = owl; + owl.Component.env = {}; /** * Symbol used in ComponentWrapper to redirect Owl events to Odoo legacy * events. */ odoo.widgetSymbol = Symbol('widget'); - - /** - * Add a new method to owl Components to ensure that no performed RPC is - * resolved/rejected when the component is destroyed. - */ - Component.prototype.rpc = function () { - return new Promise((resolve, reject) => { - return this.env.services.rpc(...arguments) - .then(result => { - if (owl.status(this) !== "destroyed") { - resolve(result); - } - }) - .catch(reason => { - if (owl.status(this) !== "destroyed") { - reject(reason); - } - }); - }); - }; - - /** - * Patch Component.__trigger method to call a hook that adds a listener - * for the triggered event just before triggering it. This is useful if - * there are legacy widgets in the ancestors. In that case, there would be - * a widgetSymbol key in the environment, corresponding to the hook to call - * (see ComponentWrapper). - */ - const originalTrigger = owl.Component.prototype.__trigger; - Component.prototype.__trigger = function (evType, payload) { - if (this.env[odoo.widgetSymbol]) { - this.env[odoo.widgetSymbol](evType); - } - originalTrigger.call(this, evType, payload); - }; })(); diff --git a/addons/web/static/src/legacy/legacy_component.js b/addons/web/static/src/legacy/legacy_component.js new file mode 100644 index 00000000000..c083ae205e0 --- /dev/null +++ b/addons/web/static/src/legacy/legacy_component.js @@ -0,0 +1,97 @@ +/** @odoo-module **/ + +const hasOwnProperty = Object.prototype.hasOwnProperty; + +/** + * @deprecated + * This component SHOULD NOT be used! + * It's used in legacy when components should work like in owl 1. + * + * If you need to get the component's `el` then use `useRef` + * and if you need to send info to the component's parent then use props. + * + * e.g. + * // OWL 1 + * class Component_OWL1 extends owl.Component { + * static template = owl.tags.xml` + * + * `; + * mounted() { + * this.el.style = "color: red"; + * } + * } + * + * // OWL 2 + * class Component_OWL2 extends owl.Component { + * static template = owl.xml` + * + * `; + * setup() { + * this.btnRef = useRef("btn"); + * owl.onMounted(() => { + * this.btnRef.el.style = "color: red"; + * }); + * } + * } + */ +export class LegacyComponent extends owl.Component { + get el() { + const bdom = this.__owl__.bdom; + if (!bdom) { + return null; + } + + if (hasOwnProperty.call(bdom, "component")) { + return bdom.component.el; + } else { + return bdom.firstNode(); + } + } + /** + * Add a new method to owl Components to ensure that no performed RPC is + * resolved/rejected when the component is destroyed. + */ + rpc() { + return new Promise((resolve, reject) => { + return this.env.services + .rpc(...arguments) + .then((result) => { + if (owl.status(this) !== "destroyed") { + resolve(result); + } + }) + .catch((reason) => { + if (owl.status(this) !== "destroyed") { + reject(reason); + } + }); + }); + } + + /** + * Emit a custom event of type 'eventType' with the given 'payload' on the + * component's el, if it exists. However, note that the event will only bubble + * up to the parent DOM nodes. Thus, it must be called between mounted() and + * willUnmount(). + */ + trigger(eventType, payload) { + this.__trigger(eventType, payload); + } + /** + * Private trigger method, allows to choose the component which triggered + * the event in the first place + */ + __trigger(eventType, payload) { + if (this.env[odoo.widgetSymbol]) { + this.env[odoo.widgetSymbol](eventType); + } + if (this.el) { + const ev = new CustomEvent(eventType, { + bubbles: true, + cancelable: true, + detail: payload, + }); + this.el.dispatchEvent(ev); + } + } +} diff --git a/addons/web/static/src/owl2_compatibility/component.js b/addons/web/static/src/owl2_compatibility/component.js deleted file mode 100644 index 259922aad9d..00000000000 --- a/addons/web/static/src/owl2_compatibility/component.js +++ /dev/null @@ -1,43 +0,0 @@ -(function () { - const hasOwnProperty = Object.prototype.hasOwnProperty; - - owl.Component = class extends owl.Component { - get el() { - const bdom = this.__owl__.bdom; - if (!bdom) { - return null; - } - - if (hasOwnProperty.call(bdom, "component")) { - return bdom.component.el; - } else { - return bdom.firstNode(); - } - } - - /** - * Emit a custom event of type 'eventType' with the given 'payload' on the - * component's el, if it exists. However, note that the event will only bubble - * up to the parent DOM nodes. Thus, it must be called between mounted() and - * willUnmount(). - */ - trigger(eventType, payload) { - this.__trigger(eventType, payload); - } - /** - * Private trigger method, allows to choose the component which triggered - * the event in the first place - */ - __trigger(eventType, payload) { - if (this.el) { - const ev = new CustomEvent(eventType, { - bubbles: true, - cancelable: true, - detail: payload, - }); - this.el.dispatchEvent(ev); - } - } - }; - owl.Component.env = {}; -})();