diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/web/doc/client_action.rst | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/web/doc/client_action.rst')
| -rw-r--r-- | addons/web/doc/client_action.rst | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/addons/web/doc/client_action.rst b/addons/web/doc/client_action.rst new file mode 100644 index 00000000..4852400d --- /dev/null +++ b/addons/web/doc/client_action.rst @@ -0,0 +1,114 @@ +.. highlight:: javascript + +Client actions +============== + +Client actions are the client-side version of OpenERP's "Server +Actions": instead of allowing for semi-arbitrary code to be executed +in the server, they allow for execution of client-customized code. + +On the server side, a client action is an action of type +``ir.actions.client``, which has (at most) two properties: a mandatory +``tag``, which is an arbitrary string by which the client will +identify the action, and an optional ``params`` which is simply a map +of keys and values sent to the client as-is (this way, client actions +can be made generic and reused in multiple contexts). + +General Structure +----------------- + +In the OpenERP Web code, a client action only requires two pieces of +information: + +* Mapping the action's ``tag`` to an object + +* Providing said object. Two different types of objects can be mapped + to a client action: + + * An OpenERP Web widget, which must inherit from + :js:class:`openerp.web.Widget` + + * A regular javascript function + +The major difference is in the lifecycle of these: + +* if the client action maps to a function, the function will be called + when executing the action. The function can have no further + interaction with the Web Client itself, although it can return an + action which will be executed after it. + + The function takes 2 parameters: the ActionManager calling it and + the descriptor for the current action (the ``ir.actions.client`` + dictionary). + +* if, on the other hand, the client action maps to a + :js:class:`~openerp.web.Widget`, that + :js:class:`~openerp.web.Widget` will be instantiated and added to + the web client's canvas, with the usual + :js:class:`~openerp.web.Widget` lifecycle (essentially, it will + either take over the content area of the client or it will be + integrated within a dialog). + +For example, to create a client action displaying a ``res.widget`` +object:: + + // Registers the object 'openerp.web_dashboard.Widget' to the client + // action tag 'board.home.widgets' + instance.web.client_actions.add( + 'board.home.widgets', 'instance.web_dashboard.Widget'); + instance.web_dashboard.Widget = instance.web.Widget.extend({ + template: 'HomeWidget' + }); + +At this point, the generic :js:class:`~openerp.web.Widget` lifecycle +takes over, the template is rendered, inserted in the client DOM, +bound on the object's ``$el`` property and the object is started. + +The second parameter to the constructor is the descriptor for the +action itself, which contains any parameter provided:: + + init: function (parent, action) { + // execute the Widget's init + this._super(parent); + // board.home.widgets only takes a single param, the identifier of the + // res.widget object it should display. Store it for later + this.widget_id = action.params.widget_id; + } + +More complex initialization (DOM manipulations, RPC requests, ...) +should be performed in the :js:func:`~openerp.web.Widget.start()` +method. + +.. note:: + + As required by :js:class:`~openerp.web.Widget`'s contract, if + :js:func:`~openerp.web.Widget.start()` executes any asynchronous + code it should return a ``Promise`` so callers know when it's + ready for interaction. + +.. code-block:: javascript + + start: function () { + return Promise.all([ + this._super(), + // Simply read the res.widget object this action should display + new instance.web.Model('res.widget').call( + 'read', [[this.widget_id], ['title']]) + .then(this.proxy('on_widget_loaded') + ]); + } + +The client action can then behave exactly as it wishes to within its +root (``this.$el``). In this case, it performs further renderings once +its widget's content is retrieved:: + + on_widget_loaded: function (widgets) { + var widget = widgets[0]; + var url = _.sprintf( + '/web_dashboard/widgets/content?session_id=%s&widget_id=%d', + this.session.session_id, widget.id); + this.$el.html(QWeb.render('HomeWidget.content', { + widget: widget, + url: url + })); + } |
