[FIX] Inject user context in all domain and context evaluation
[odoo/odoo.git] / addons / web / doc / client_action.rst
1 .. highlight:: javascript
2
3 Client actions
4 ==============
5
6 Client actions are the client-side version of OpenERP's "Server
7 Actions": instead of allowing for semi-arbitrary code to be executed
8 in the server, they allow for execution of client-customized code.
9
10 On the server side, a client action is an action of type
11 ``ir.actions.client``, which has (at most) two properties: a mandatory
12 ``tag``, which is an arbitrary string by which the client will
13 identify the action, and an optional ``params`` which is simply a map
14 of keys and values sent to the client as-is (this way, client actions
15 can be made generic and reused in multiple contexts).
16
17 General Structure
18 -----------------
19
20 In the OpenERP Web code, a client action only requires two pieces of
21 information:
22
23 * Mapping the action's ``tag`` to an object
24
25 * Providing said object. Two different types of objects can be mapped
26   to a client action:
27
28   * An OpenERP Web widget, which must inherit from
29     :js:class:`openerp.web.Widget`
30
31   * A regular javascript function
32
33 The major difference is in the lifecycle of these:
34
35 * if the client action maps to a function, the function will be called
36   when executing the action. The function can have no further
37   interaction with the Web Client itself, although it can return an
38   action which will be executed after it.
39
40   The function takes 2 parameters: the ActionManager calling it and
41   the descriptor for the current action (the ``ir.actions.client``
42   dictionary).
43
44 * if, on the other hand, the client action maps to a
45   :js:class:`~openerp.web.Widget`, that
46   :js:class:`~openerp.web.Widget` will be instantiated and added to
47   the web client's canvas, with the usual
48   :js:class:`~openerp.web.Widget` lifecycle (essentially, it will
49   either take over the content area of the client or it will be
50   integrated within a dialog).
51
52 For example, to create a client action displaying a ``res.widget``
53 object::
54
55     // Registers the object 'openerp.web_dashboard.Widget' to the client
56     // action tag 'board.home.widgets'
57     instance.web.client_actions.add(
58         'board.home.widgets', 'instance.web_dashboard.Widget');
59     instance.web_dashboard.Widget = instance.web.Widget.extend({
60         template: 'HomeWidget'
61     });
62
63 At this point, the generic :js:class:`~openerp.web.Widget` lifecycle
64 takes over, the template is rendered, inserted in the client DOM,
65 bound on the object's ``$el`` property and the object is started.
66
67 The second parameter to the constructor is the descriptor for the
68 action itself, which contains any parameter provided::
69
70     init: function (parent, action) {
71         // execute the Widget's init
72         this._super(parent);
73         // board.home.widgets only takes a single param, the identifier of the
74         // res.widget object it should display. Store it for later
75         this.widget_id = action.params.widget_id;
76     }
77
78 More complex initialization (DOM manipulations, RPC requests, ...)
79 should be performed in the :js:func:`~openerp.web.Widget.start()`
80 method.
81
82 .. note::
83
84     As required by :js:class:`~openerp.web.Widget`'s contract, if
85     :js:func:`~openerp.web.Widget.start()` executes any asynchronous
86     code it should return a ``$.Deferred`` so callers know when it's
87     ready for interaction.
88
89 .. code-block:: javascript
90
91     start: function () {
92         return $.when(
93             this._super(),
94             // Simply read the res.widget object this action should display
95             new instance.web.Model('res.widget').call(
96                 'read', [[this.widget_id], ['title']])
97                     .then(this.proxy('on_widget_loaded'));
98     }
99
100 The client action can then behave exactly as it wishes to within its
101 root (``this.$el``). In this case, it performs further renderings once
102 its widget's content is retrieved::
103
104     on_widget_loaded: function (widgets) {
105         var widget = widgets[0];
106         var url = _.sprintf(
107             '/web_dashboard/widgets/content?session_id=%s&widget_id=%d',
108             this.session.session_id, widget.id);
109         this.$el.html(QWeb.render('HomeWidget.content', {
110             widget: widget,
111             url: url
112         }));
113     }