diff --git a/doc/reference/javascript_cheatsheet.rst b/doc/reference/javascript_cheatsheet.rst
index ea22e8f4715..c4d403b6b8e 100644
--- a/doc/reference/javascript_cheatsheet.rst
+++ b/doc/reference/javascript_cheatsheet.rst
@@ -130,51 +130,6 @@ This is usually done with code looking like this:
});
-Adding a client action
-======================
-
-A client action is a widget which will control the part of the screen below the
-menu bar. It can have a control panel, if necessary. Defining a client action
-can be done in two steps: implementing a new widget, and registering the widget
-in the action registry.
-
-- Implementing a new client action:
- This is done by creating a widget:
-
- .. code-block:: javascript
-
- var ControlPanelMixin = require('web.ControlPanelMixin');
- var AbstractAction = require('web.AbstractAction');
-
- var ClientAction = AbstractAction.extend(ControlPanelMixin, {
- ...
- });
-
- Do not add the controlpanel mixin if you do not need it. Note that some
- code is needed to interact with the control panel (via the
- ``update_control_panel`` method given by the mixin).
-
-- Registering the client action:
- As usual, we need to make the web client aware of the mapping between
- client actions and the actual class:
-
- .. code-block:: javascript
-
- var core = require('web.core');
-
- core.action_registry.add('my-custom-action', ClientAction);
-
-
- Then, to use the client action in the web client, we need to create a client
- action record (a record of the model ``ir.actions.client``) with the proper
- ``tag`` attribute:
-
- .. code-block:: xml
-
-
- Some Name
- my-custom-action
-
Creating a new view (from scratch)
==================================
diff --git a/doc/reference/javascript_reference.rst b/doc/reference/javascript_reference.rst
index 8089fd1205e..c8572a6fad7 100644
--- a/doc/reference/javascript_reference.rst
+++ b/doc/reference/javascript_reference.rst
@@ -616,23 +616,23 @@ Widget API
generated DOM root with the following attributes:
- .. attribute:: Widget.id
+.. attribute:: Widget.id
- Used to generate an ``id`` attribute on the generated DOM
- root. Note that this is rarely needed, and is probably not a good idea
- if a widget can be used more than once.
+ Used to generate an ``id`` attribute on the generated DOM
+ root. Note that this is rarely needed, and is probably not a good idea
+ if a widget can be used more than once.
- .. attribute:: Widget.className
+.. attribute:: Widget.className
- Used to generate a ``class`` attribute on the generated DOM root. Note
- that it can actually contain more than one css class:
- *'some-class other-class'*
+ Used to generate a ``class`` attribute on the generated DOM root. Note
+ that it can actually contain more than one css class:
+ *'some-class other-class'*
- .. attribute:: Widget.attributes
+.. attribute:: Widget.attributes
- Mapping (object literal) of attribute names to attribute
- values. Each of these k:v pairs will be set as a DOM attribute
- on the generated DOM root.
+ Mapping (object literal) of attribute names to attribute
+ values. Each of these k:v pairs will be set as a DOM attribute
+ on the generated DOM root.
.. attribute:: Widget.el
@@ -651,13 +651,21 @@ Widget API
initialized but before it has been started. The root element generated by
the template will be set as the DOM root of the widget.
-.. attribute:: xmlDependencies
+.. attribute:: Widget.xmlDependencies
List of paths to xml files that need to be loaded before the
widget can be rendered. This will not induce loading anything that has already
- been loaded.
+ been loaded. This is useful when you want to load your templates lazily,
+ or if you want to share a widget between the website and the web client
+ interface.
-.. attribute:: events
+ .. code-block:: javascript
+
+ var EditorMenuBar = Widget.extend({
+ xmlDependencies: ['/web_editor/static/src/xml/editor.xml'],
+ ...
+
+.. attribute:: Widget.events
Events are a mapping of an event selector (an event name and an optional
CSS selector separated by a space) to a callback. The callback can
@@ -682,7 +690,7 @@ Widget API
Note: the use of an inline function is discouraged, and will probably be
removed sometimes in the future.
-.. attribute:: custom_events
+.. attribute:: Widget.custom_events
this is almost the same as the *events* attribute, but the keys
are arbitrary strings. They represent business events triggered by
@@ -1265,6 +1273,55 @@ when the module is loaded.
Note that translation functions need some care. The string given in argument
should not be dynamic.
+Session
+=======
+
+There is a specific module provided by the web client which contains some
+information specific to the user current *session*. Some notable keys are
+
+- uid: the current user ID (its ID as a *res.users*)
+- user_name: the user name, as a string
+- the user context (user ID, language and timezone)
+- partner_id: the ID of the partner associated to the current user
+- db: the name of the database currently being in use
+
+Adding information to the session
+---------------------------------
+
+When the /web route is loaded, the server will inject some session information
+in the template a script tag. The information will be read from the method
+*session_info* of the model *ir.http*. So, if one wants to add a specific
+information, it can be done by overriding the session_info method and adding it
+to the dictionary.
+
+.. code-block:: python
+
+ from odoo import models
+ from odoo.http import request
+
+
+ class IrHttp(models.AbstractModel):
+ _inherit = 'ir.http'
+
+ def session_info(self):
+ result = super(IrHttp, self).session_info()
+ result['some_key'] = get_some_value_from_db()
+ return result
+
+Now, the value can be obtained in javascript by reading it in the session:
+
+.. code-block:: javascript
+
+ var session = require('web.session');
+ var myValue = session.some_key;
+ ...
+
+Note that this mechanism is designed to reduce the amount of communication
+needed by the web client to be ready. It is more appropriate for data which is
+cheap to compute (a slow session_info call will delay the loading for the web
+client for everyone), and for data which is required early in the initialization
+process.
+
Views
======
@@ -1400,6 +1457,7 @@ order.
Options:
- type: setting the input type (*text* by default, can be set on *number*)
+
On edit mode, the field is rendered as an input with the HTML attribute type
setted on *number* (so user can benefit the native support, especially on
mobile). In this case, the default formatting is disabled to avoid incompability.
@@ -1409,7 +1467,7 @@ order.
- step: set the step to the value up and down when the user click on buttons
- (only for input of type number, 1 by default)
+ (only for input of type number, 1 by default)
.. code-block:: xml
@@ -1431,6 +1489,7 @@ order.
Options:
- type: setting the input type (*text* by default, can be set on *number*)
+
On edit mode, the field is rendered as an input with the HTML attribute type
setted on *number* (so user can benefit the native support, especially on
mobile). In this case, the default formatting is disabled to avoid incompability.
@@ -1440,7 +1499,7 @@ order.
- step: set the step to the value up and down when the user click on buttons
- (only for input of type number, 1 by default)
+ (only for input of type number, 1 by default)
.. code-block:: xml
@@ -1996,6 +2055,122 @@ Relational fields
This widget is exactly the same as a FieldOne2Many. It is registered at this
key only for backward compatibility reasons. Please avoid using this.
+
+Client actions
+==============
+
+The idea of a client action is a customized widget that is integrated in the
+web client interface, just like a *act_window_action*. This is useful when
+you need a component that is not closely linked to an existing view or a
+specific model. For example, the Discuss application is actually a client
+action.
+
+A client action is a term that has various meanings, depending on the context:
+
+- from the perspective of the server, it is a record of the model *ir_action*,
+ with a field *tag* of type char
+- from the perspective of the web client, it is a widget, which inherit from
+ the class AbstractAction, and is supposed to be registered in the
+ action registry under the corresponding key (from the field char)
+
+Whenever a menu item is associated to a client action, opening it will simply
+fetch the action definition from the server, then lookup into its action
+registry to get the Widget definition at the appropriate key, and finally, it
+will instantiate and append the widget to the proper place in the DOM.
+
+Adding a client action
+----------------------
+
+A client action is a widget which will control the part of the screen below the
+menu bar. It can have a control panel, if necessary. Defining a client action
+can be done in two steps: implementing a new widget, and registering the widget
+in the action registry.
+
+- Implementing a new client action:
+ This is done by creating a widget:
+
+ .. code-block:: javascript
+
+ var ControlPanelMixin = require('web.ControlPanelMixin');
+ var AbstractAction = require('web.AbstractAction');
+
+ var ClientAction = AbstractAction.extend(ControlPanelMixin, {
+ ...
+ });
+
+ Do not add the controlpanel mixin if you do not need it. Note that some
+ code is needed to interact with the control panel (via the
+ ``update_control_panel`` method given by the mixin).
+
+- Registering the client action:
+ As usual, we need to make the web client aware of the mapping between
+ client actions and the actual class:
+
+ .. code-block:: javascript
+
+ var core = require('web.core');
+
+ core.action_registry.add('my-custom-action', ClientAction);
+
+
+ Then, to use the client action in the web client, we need to create a client
+ action record (a record of the model ``ir.actions.client``) with the proper
+ ``tag`` attribute:
+
+ .. code-block:: xml
+
+
+ Some Name
+ my-custom-action
+
+
+
+Using the control panel mixin
+-----------------------------
+
+By default, the AbstractAction class does not include the control panel mixin.
+This means that a client action does not display a control panel. In order to
+do that, several steps should be done.
+
+- add ControlPanelMixin in the widget:
+
+ .. code-block:: javascript
+
+ var ControlPanelMixin = require('web.ControlPanelMixin');
+
+ var MyClientAction = AbstractAction.extend(ControlPanelMixin, {
+ ...
+ });
+
+- call the method *update_control_panel* whenever we need to update the control
+ panel. For example:
+
+ .. code-block:: javascript
+
+ var SomeClientAction = Widget.extend(ControlPanelMixin, {
+ ...
+ start: function () {
+ this._renderButtons();
+ this._updateControlPanel();
+ ...
+ },
+ do_show: function () {
+ ...
+ this._updateControlPanel();
+ },
+ _renderButtons: function () {
+ this.$buttons = $(QWeb.render('SomeTemplate.Buttons'));
+ this.$buttons.on('click', ...);
+ },
+ _updateControlPanel: function () {
+ this.update_control_panel({
+ cp_content: {
+ $buttons: this.$buttons,
+ },
+ });
+
+For more information, look into the *control_panel.js* file.
+
.. _.appendTo():
http://api.jquery.com/appendTo/