[ADD] developer: add javascript module page
This commit moves most of the content out of the javascript reference
and into a more visible page.
closes odoo/documentation#1211
X-original-commit: c6f813f4cb
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
parent
34565a1608
commit
32de28100e
@ -1,13 +1,14 @@
|
||||
:nosearch:
|
||||
|
||||
==================
|
||||
Javascript Modules
|
||||
==================
|
||||
==========
|
||||
Javascript
|
||||
==========
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
javascript/framework_overview
|
||||
javascript/javascript_modules
|
||||
javascript/owl_component_system
|
||||
javascript/javascript_cheatsheet
|
||||
javascript/javascript_reference
|
||||
|
390
content/developer/reference/javascript/javascript_modules.rst
Normal file
390
content/developer/reference/javascript/javascript_modules.rst
Normal file
@ -0,0 +1,390 @@
|
||||
==================
|
||||
Javascript Modules
|
||||
==================
|
||||
|
||||
Odoo supports three different kinds of javascript files:
|
||||
|
||||
- :ref:`plain javascript files <javascript/plain_javascript>` (no module system),
|
||||
- :ref:`native javascript module <javascript/native_js_module>`.
|
||||
- :ref:`Odoo modules <javascript/odoo_module>` (using a custom module system),
|
||||
|
||||
As described in the :ref:`assets management section <javascript/assets_management>`,
|
||||
all javascript files are bundled together and served to the browser.
|
||||
Note that native javascript files are processed by the Odoo server and transformed into Odoo custom modules.
|
||||
|
||||
Let us briefly explain the purpose behind each kind of javascript file. Plain
|
||||
javascript files should be reserved only for external libraries and some small
|
||||
specific low level purposes. All new javascript files should be created in the
|
||||
native javascript module system. The custom module system is only useful for old,
|
||||
not yet converted files.
|
||||
|
||||
.. _javascript/plain_javascript:
|
||||
|
||||
Plain Javascript files
|
||||
======================
|
||||
|
||||
Plain javascript files can contain arbitrary content. It is advised to use the
|
||||
*iife* :dfn:`immediately invoked function execution` style when writing such a file:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
(function () {
|
||||
// some code here
|
||||
let a = 1;
|
||||
console.log(a);
|
||||
})();
|
||||
|
||||
The advantages of such files is that we avoid leaking local variables to the
|
||||
global scope.
|
||||
|
||||
Clearly, plain javascript files do not offer the benefits of a module system, so
|
||||
one needs to be careful about the order in the bundle (since the browser will
|
||||
execute them precisely in that order).
|
||||
|
||||
.. note::
|
||||
In Odoo, all external libraries are loaded as plain javascript files.
|
||||
|
||||
.. _javascript/native_js_module:
|
||||
|
||||
Native Javascript Modules
|
||||
=========================
|
||||
|
||||
Most new Odoo javascript code should use the native javascript module system. This
|
||||
is simpler, and brings the benefits of a better developer experience with a better
|
||||
integration with the IDE.
|
||||
|
||||
There is a very important point to know: Odoo needs to know which files
|
||||
should be translated into :ref:`Odoo modules <javascript/odoo_module>` and which
|
||||
files should not be translated. This is an opt-in system: Odoo will look at the
|
||||
first line of a JS file and check if it contains the string *@odoo-module*. If so, it will
|
||||
automatically be converted to an Odoo module.
|
||||
|
||||
For example, let us consider the following module, located in :file:`web/static/src/file_a.js`:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
Note the comment in the first line: it describes that this file should be converted.
|
||||
Any file without this comment will be kept as-is (which will most likely be an
|
||||
error). This file will then be translated into an Odoo module that look like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('@web/file_a', function (require) {
|
||||
'use strict';
|
||||
let __exports = {};
|
||||
|
||||
const { someFunction } = require("@web/file_b");
|
||||
|
||||
__exports.otherFunction = function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
};
|
||||
|
||||
return __exports;
|
||||
)};
|
||||
|
||||
So, as you can see, the transformation is basically adding `odoo.define` on top,
|
||||
and updating the import/export statements.
|
||||
|
||||
Another important point is that the translated module has an official name:
|
||||
*@web/file_a*. This is the actual name of the module. Every relative imports
|
||||
will be converted as well. Every file located in an Odoo addon
|
||||
:file:`some_addon/static/src/path/to/file.js` will be assigned a name prefixed by the
|
||||
addon name like this: *@some_addon/path/to/file*.
|
||||
|
||||
Relative imports work, but only if the modules are in the same Odoo addon. So, imagine that we have
|
||||
the following file structure:
|
||||
|
||||
::
|
||||
|
||||
addons/
|
||||
web/
|
||||
static/
|
||||
src/
|
||||
file_a.js
|
||||
file_b.js
|
||||
stock/
|
||||
static/
|
||||
src/
|
||||
file_c.js
|
||||
|
||||
The file :file:`file_b` can import :file:`file_a` like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import {something} from `./file_a`
|
||||
|
||||
But :file:`file_c` need to use the full name:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import {something} from `@web/file_a`
|
||||
|
||||
|
||||
Aliased modules
|
||||
---------------
|
||||
|
||||
Because :ref:`Odoo modules <javascript/odoo_module>` follow a different module naming pattern, a system exists to allow a smooth
|
||||
transition towards the new system. Currently, if a file is converted to a module (and therefore
|
||||
follow the new naming convention), other files not yet converted to ES6-like syntax in the project
|
||||
won't be able to require the module. Aliases are here to map old names with new ones by creating a
|
||||
small proxy function. The module can then be called by its new *and* old name.
|
||||
|
||||
To add such alias, the comment tag on top of the file should look like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module alias=web.someName**/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export default function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
Then, the translated module will also create an alias with the requested name:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define(`web.someName`, function(require) {
|
||||
return require('@web/file_a')[Symbol.for("default")];
|
||||
});
|
||||
|
||||
The default behaviour of aliases is to re-export the ``default`` value of the
|
||||
module they alias. This is because "classic" modules generally export a single
|
||||
value which would be used directly, roughly matching the semantics of default
|
||||
exports.
|
||||
However it is also possible to delegate more directly, and follow the exact
|
||||
behaviour of the aliased module:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module alias=web.someName default=0**/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
In that case, this will define an alias with exactly the values exported by the
|
||||
original module:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define(`web.someName`, function(require) {
|
||||
return require('@web/file_a');
|
||||
});
|
||||
|
||||
.. note::
|
||||
Only one alias can be defined using this method. If you were to need another one to have, for
|
||||
example, three names to call the same module, you would have to add a proxy manually.
|
||||
This is not good practice and should be avoided unless there is no other options.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
For performance reasons, Odoo does not use a full javascript
|
||||
parser to transform native modules. There are, therefore, a number of limitations including but not
|
||||
limited to:
|
||||
|
||||
- an `import` or `export` keyword cannot be preceded by a non-space character,
|
||||
- a multiline comment or string cannot have a line starting by `import` or `export`
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// supported
|
||||
import X from "xxx";
|
||||
export X;
|
||||
export default X;
|
||||
import X from "xxx";
|
||||
|
||||
/*
|
||||
* import X ...
|
||||
*/
|
||||
|
||||
/*
|
||||
* export X
|
||||
*/
|
||||
|
||||
|
||||
// not supported
|
||||
|
||||
var a= 1;import X from "xxx";
|
||||
/*
|
||||
import X ...
|
||||
*/
|
||||
|
||||
- when you export an object, it can't contain a comment
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// supported
|
||||
export {
|
||||
a as b,
|
||||
c,
|
||||
d,
|
||||
}
|
||||
|
||||
export {
|
||||
a
|
||||
} from "./file_a"
|
||||
|
||||
|
||||
// not supported
|
||||
export {
|
||||
a as b, // this is a comment
|
||||
c,
|
||||
d,
|
||||
}
|
||||
|
||||
export {
|
||||
a /* this is a comment */
|
||||
} from "./file_a"
|
||||
|
||||
- Odoo needs a way to determine if a module is described by a path (like :file:`./views/form_view`)
|
||||
or a name (like `web.FormView`). It has to use a heuristic to do just that: if there is a `/` in
|
||||
the name, it is considered a path. This means that Odoo does not really support module names with
|
||||
a `/` anymore.
|
||||
|
||||
As "classic" modules are not deprecated and there is currently no plan to remove them, you can and should keep using
|
||||
them if you encounter issues with, or are constrained by the limitations of, native modules. Both styles can coexist
|
||||
within the same Odoo addon.
|
||||
|
||||
|
||||
.. _javascript/odoo_module:
|
||||
|
||||
Odoo Module System
|
||||
===================
|
||||
|
||||
Odoo has defined a small module system (located in the file
|
||||
:file:`addons/web/static/src/js/boot.js`, which needs to be loaded first). The Odoo
|
||||
module system, inspired by AMD, works by defining the function `define`
|
||||
on the global odoo object. We then define each javascript module by calling that
|
||||
function. In the Odoo framework, a module is a piece of code that will be executed
|
||||
as soon as possible. It has a name and potentially some dependencies. When its
|
||||
dependencies are loaded, a module will then be loaded as well. The value of the
|
||||
module is then the return value of the function defining the module.
|
||||
|
||||
As an example, it may look like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// in file a.js
|
||||
odoo.define('module.A', function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = ...;
|
||||
|
||||
return A;
|
||||
});
|
||||
|
||||
// in file b.js
|
||||
odoo.define('module.B', function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = require('module.A');
|
||||
|
||||
var B = ...; // something that involves A
|
||||
|
||||
return B;
|
||||
});
|
||||
|
||||
An alternative way to define a module is to give explicitly a list of dependencies
|
||||
in the second argument.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', ['module.A', 'module.B'], function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = require('module.A');
|
||||
var B = require('module.B');
|
||||
|
||||
// some code
|
||||
});
|
||||
|
||||
|
||||
If some dependencies are missing/non ready, then the module will simply not be
|
||||
loaded. There will be a warning in the console after a few seconds.
|
||||
|
||||
Note that circular dependencies are not supported. It makes sense, but it means that one
|
||||
needs to be careful.
|
||||
|
||||
Defining a module
|
||||
-----------------
|
||||
|
||||
The `odoo.define` method is given three arguments:
|
||||
|
||||
- `moduleName`: the name of the javascript module. It should be a unique string.
|
||||
The convention is to have the name of the odoo addon followed by a specific
|
||||
description. For example, `web.Widget` describes a module defined in the `web`
|
||||
addon, which exports a `Widget` class (because the first letter is capitalized)
|
||||
|
||||
If the name is not unique, an exception will be thrown and displayed in the
|
||||
console.
|
||||
|
||||
- `dependencies`: the second argument is optional. If given, it should be a list
|
||||
of strings, each corresponding to a javascript module. This describes the
|
||||
dependencies that are required to be loaded before the module is executed. If
|
||||
the dependencies are not explicitly given here, then the module system will
|
||||
extract them from the function by calling toString on it, then using a regexp
|
||||
to find all the `require` statements.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', ['web.ajax'], function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
|
||||
// some code here
|
||||
return something;
|
||||
});
|
||||
|
||||
- finally, the last argument is a function which defines the module. Its return
|
||||
value is the value of the module, which may be passed to other modules requiring
|
||||
it. Note that there is a small exception for asynchronous modules, see the
|
||||
next section.
|
||||
|
||||
If an error happens, it will be logged (in debug mode) in the console:
|
||||
|
||||
* `Missing dependencies`:
|
||||
These modules do not appear in the page. It is possible that the JavaScript
|
||||
file is not in the page or that the module name is wrong
|
||||
* `Failed modules`:
|
||||
A javascript error is detected
|
||||
* `Rejected modules`:
|
||||
The module returns a rejected Promise. It (and its dependent modules) is not
|
||||
loaded.
|
||||
* `Rejected linked modules`:
|
||||
Modules who depend on a rejected module
|
||||
* `Non loaded modules`:
|
||||
Modules who depend on a missing or a failed module
|
||||
|
||||
Asynchronous modules
|
||||
---------------------
|
||||
|
||||
It can happen that a module needs to perform some work before it is ready. For
|
||||
example, it could do an rpc to load some data. In that case, the module can
|
||||
simply return a promise. The module system will simply
|
||||
wait for the promise to complete before registering the module.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
|
||||
return ajax.rpc(...).then(function (result) {
|
||||
// some code here
|
||||
return something;
|
||||
});
|
||||
});
|
@ -75,6 +75,8 @@ We only cover the most important files/folders.
|
||||
- *fields*: all main view field widgets are defined here
|
||||
- *views*: this is where the views are located
|
||||
|
||||
.. _javascript/assets_management:
|
||||
|
||||
Assets Management
|
||||
=================
|
||||
|
||||
@ -421,10 +423,10 @@ For most Odoo code, we want to use a module system. Because of the way assets
|
||||
work in Odoo (and in particular, the fact that each installed odoo addon can
|
||||
modify the list of files contained in a bundle), Odoo has to resolve modules
|
||||
browser side. To do that, Odoo provides a small module system described just
|
||||
below (see :ref:`reference/javascript_reference/odoo_module`).
|
||||
below (see :ref:`javascript/odoo_module`).
|
||||
|
||||
However, Odoo also provides support for native javascript modules (see
|
||||
:ref:`reference/javascript_reference/js_module`). These modules
|
||||
:ref:`javascript/native_js_module`). These modules
|
||||
will simply be translated by the server into odoo modules. It is encouraged to
|
||||
write all javascript code as a native module, for a better IDE integration. In
|
||||
the future, the Odoo module system should be considered an implementation detail,
|
||||
@ -433,372 +435,6 @@ not the primary way to write javascript code.
|
||||
.. note::
|
||||
Native javascript modules are the primary way to define javascript code.
|
||||
|
||||
.. _reference/javascript_reference/odoo_module:
|
||||
|
||||
Odoo Module System
|
||||
===================
|
||||
|
||||
Odoo has defined a small module system (located in the file
|
||||
*addons/web/static/src/js/boot.js*, which needs to be loaded first). The Odoo
|
||||
module system, inspired by AMD, works by defining the function ``define``
|
||||
on the global odoo object. We then define each javascript module by calling that
|
||||
function. In the Odoo framework, a module is a piece of code that will be executed
|
||||
as soon as possible. It has a name and potentially some dependencies. When its
|
||||
dependencies are loaded, a module will then be loaded as well. The value of the
|
||||
module is then the return value of the function defining the module.
|
||||
|
||||
|
||||
As an example, it may look like this:
|
||||
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// in file a.js
|
||||
odoo.define('module.A', function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = ...;
|
||||
|
||||
return A;
|
||||
});
|
||||
|
||||
// in file b.js
|
||||
odoo.define('module.B', function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = require('module.A');
|
||||
|
||||
var B = ...; // something that involves A
|
||||
|
||||
return B;
|
||||
});
|
||||
|
||||
An alternative way to define a module is to give explicitly a list of dependencies
|
||||
in the second argument.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', ['module.A', 'module.B'], function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = require('module.A');
|
||||
var B = require('module.B');
|
||||
|
||||
// some code
|
||||
});
|
||||
|
||||
|
||||
If some dependencies are missing/non ready, then the module will simply not be
|
||||
loaded. There will be a warning in the console after a few seconds.
|
||||
|
||||
Note that circular dependencies are not supported. It makes sense, but it means that one
|
||||
needs to be careful.
|
||||
|
||||
Defining a module
|
||||
-----------------
|
||||
|
||||
The *odoo.define* method is given three arguments:
|
||||
|
||||
- *moduleName*: the name of the javascript module. It should be a unique string.
|
||||
The convention is to have the name of the odoo addon followed by a specific
|
||||
description. For example, ``web.Widget`` describes a module defined in the *web*
|
||||
addon, which exports a ``Widget`` class (because the first letter is capitalized)
|
||||
|
||||
If the name is not unique, an exception will be thrown and` displayed in the
|
||||
console.
|
||||
|
||||
- *dependencies*: the second argument is optional. If given, it should be a list
|
||||
of strings, each corresponding to a javascript module. This describes the
|
||||
dependencies that are required to be loaded before the module is executed. If
|
||||
the dependencies are not explicitly given here, then the module system will
|
||||
extract them from the function by calling toString on it, then using a regexp
|
||||
to find all ``require`` statements.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', ['web.ajax'], function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
|
||||
// some code here
|
||||
return something;
|
||||
});
|
||||
|
||||
- finally, the last argument is a function which defines the module. Its return
|
||||
value is the value of the module, which may be passed to other modules requiring
|
||||
it. Note that there is a small exception for asynchronous modules, see the
|
||||
next section.
|
||||
|
||||
If an error happens, it will be logged (in debug mode) in the console:
|
||||
|
||||
* ``Missing dependencies``:
|
||||
These modules do not appear in the page. It is possible that the JavaScript
|
||||
file is not in the page or that the module name is wrong
|
||||
* ``Failed modules``:
|
||||
A javascript error is detected
|
||||
* ``Rejected modules``:
|
||||
The module returns a rejected Promise. It (and its dependent modules) is not
|
||||
loaded.
|
||||
* ``Rejected linked modules``:
|
||||
Modules who depend on a rejected module
|
||||
* ``Non loaded modules``:
|
||||
Modules who depend on a missing or a failed module
|
||||
|
||||
|
||||
|
||||
Asynchronous modules
|
||||
---------------------
|
||||
|
||||
It can happen that a module needs to perform some work before it is ready. For
|
||||
example, it could do a rpc to load some data. In that case, the module can
|
||||
simply return a promise. In that case, the module system will simply
|
||||
wait for the promise to complete before registering the module.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
|
||||
return ajax.rpc(...).then(function (result) {
|
||||
// some code here
|
||||
return something;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Best practices
|
||||
----------------
|
||||
|
||||
- remember the convention for a module name: *addon name* suffixed with *module
|
||||
name*.
|
||||
- declare all your dependencies at the top of the module. Also, they should be
|
||||
sorted alphabetically by module name. This makes it easier to understand your module.
|
||||
- declare all exported values at the end
|
||||
- try to avoid exporting too many things from one module. It is usually better
|
||||
to simply export one thing in one (small/smallish) module.
|
||||
- asynchronous modules can be used to simplify some use cases. For example,
|
||||
the *web.dom_ready* module returns a promise which will be resolved when the
|
||||
dom is actually ready. So, another module that needs the DOM could simply have
|
||||
a `require('web.dom_ready')` statement somewhere, and the code will only be
|
||||
executed when the DOM is ready.
|
||||
- try to avoid defining more than one module in one file. It may be convenient
|
||||
in the short term, but this is actually harder to maintain.
|
||||
|
||||
|
||||
.. _reference/javascript_reference/js_module:
|
||||
|
||||
Native Javascript Modules
|
||||
=========================
|
||||
|
||||
Most new Odoo javascript code should use the native javascript module system. This
|
||||
is simpler, and brings the benefits of a better developer experience with a better
|
||||
integration with IDE.
|
||||
|
||||
There is a very important point to know: since Odoo needs to know which files
|
||||
should be translated into odoo modules and which files should not be translated,
|
||||
this is an opt-in system: Odoo will look at the first line of a JS file. If it
|
||||
contains the string *@odoo-module*, then it will be automatically converted to an
|
||||
Odoo module.
|
||||
|
||||
For example, let us consider the following module, located in *web/static/src/file_a.js*:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
Note the comment in the first line: it describes that this file should be converted.
|
||||
Any file without that comment will be kept as-is (which will most likely be an
|
||||
error). This file will then be translated into an Odoo module that look like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('@web/file_a', function (require) {
|
||||
'use strict';
|
||||
let __exports = {};
|
||||
|
||||
const { someFunction } = require("@web/file_b");
|
||||
|
||||
__exports.otherFunction = function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
};
|
||||
|
||||
return __exports;
|
||||
)};
|
||||
|
||||
So, as you can see, the transformation is basically adding ``odoo.define`` on top,
|
||||
and updating the import/export statements.
|
||||
|
||||
Another important point is that the translated module has an official name:
|
||||
*@web/file_a*. This is the actual name of the module. Every relative imports
|
||||
will be converted as well. Every file located in an Odoo addon
|
||||
*some_addon/static/src/path/to/file.js* will be assigned a name prefixed by the
|
||||
addon name like this: *@some_addon/path/to/file*.
|
||||
|
||||
|
||||
Relative imports work, but only inside an odoo addon. So, imagine that we have
|
||||
the following file structure:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
addons/
|
||||
web/
|
||||
static/
|
||||
src/
|
||||
file_a.js
|
||||
file_b.js
|
||||
stock/
|
||||
static/
|
||||
src/
|
||||
file_c.js
|
||||
|
||||
The file ``file_b`` can import ``file_a`` like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import {something} from `./file_a`
|
||||
|
||||
But ``file_c`` need to use the full name:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import {something} from `@web/file_a`
|
||||
|
||||
|
||||
Aliased modules
|
||||
---------------
|
||||
|
||||
Because Odoo modules follow a different module naming pattern, a system exists to allow a smoother transition towards
|
||||
the new system. Currently, if a file is converted to a module (and therefore follow the new naming convention),
|
||||
other files not yet converted to ES6-like syntax in the project won't be able to require the module. Aliases are
|
||||
here to map old names with new ones by creating a small proxy function. The module can then be called by its new
|
||||
*and* old name.
|
||||
|
||||
To add such alias, the comment tag on top of the file should look like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module alias=web.someName**/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export default function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
Then the translated module will also create an alias with the requested name:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define(`web.someName`, function(require) {
|
||||
return require('@web/file_a')[Symbol.for("default")];
|
||||
});
|
||||
|
||||
The default behaviour of aliases is to re-export the ``default`` value of the
|
||||
module they alias. This is because "classic" modules generally export a single
|
||||
value which would be used directly, roughly matching the semantics of default
|
||||
exports.
|
||||
However it is also possible to delegate more directly, and follow the exact
|
||||
behaviour of the aliased module:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module alias=web.someName default=0**/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
In that case, this will define an alias with exactly the values exported by the
|
||||
original module:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define(`web.someName`, function(require) {
|
||||
return require('@web/file_a');
|
||||
});
|
||||
|
||||
.. note::
|
||||
Only one alias can be defined using this method. If you were to need another one to have, by example, three
|
||||
names to call the same module, you will have to manually add yourself a proxy. This is not good practice and
|
||||
should be avoided unless there is no other options.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
For performance reasons, Odoo does not use a full javascript
|
||||
parser to transform native modules. There are, therefore, a number of limitations including but not limited to:
|
||||
|
||||
- an ``import`` or ``export`` keyword cannot be preceded by a non space character,
|
||||
- a multiline comment or string cannot have a line starting by ``import`` or ``export``
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// supported
|
||||
import X from "xxx";
|
||||
export X;
|
||||
export default X;
|
||||
import X from "xxx";
|
||||
|
||||
/*
|
||||
* import X ...
|
||||
*/
|
||||
|
||||
/*
|
||||
* export X
|
||||
*/
|
||||
|
||||
|
||||
// not supported
|
||||
|
||||
var a= 1;import X from "xxx";
|
||||
/*
|
||||
import X ...
|
||||
*/
|
||||
|
||||
- when you ``export`` an object, it can't contain a comment
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// supported
|
||||
export {
|
||||
a as b,
|
||||
c,
|
||||
d,
|
||||
}
|
||||
|
||||
export {
|
||||
a
|
||||
} from "./file_a"
|
||||
|
||||
|
||||
// not supported
|
||||
export {
|
||||
a as b, // this is a comment
|
||||
c,
|
||||
d,
|
||||
}
|
||||
|
||||
export {
|
||||
a /* this is a comment */
|
||||
} from "./file_a"
|
||||
|
||||
- Odoo needs a way to determine if a module is described by a path (like ``./views/form_view``) or a name (like
|
||||
``web.FormView``). It has to use a heuristic to do just that: if there is a ``/`` in the name, it is considered
|
||||
a path. This means that Odoo does not really support anymore module names with a ``/``.
|
||||
|
||||
As "classic" modules are not deprecated and there is currently no plan to remove them, you can and should keep using
|
||||
them if you encounter issues with or are constrained by the limitations of native modules. Both styles can coexist
|
||||
within the same Odoo addon.
|
||||
|
||||
|
||||
Class System
|
||||
|
Loading…
Reference in New Issue
Block a user