[MERGE} from trunk
[odoo/odoo.git] / doc / list-view.rst
1 List View
2 =========
3
4 Style Hooks
5 -----------
6
7 The list view provides a few style hook classes for re-styling of list views in
8 various situations:
9
10 ``.oe_list``
11
12     The root element of the list view, styling rules should be rooted
13     on that class.
14
15 ``table.oe_list_content``
16
17     The root table for the listview, accessory components may be
18     generated or added outside this section, this is the list view
19     "proper".
20
21 ``.oe_list_buttons``
22
23     The action buttons array for the list view, with its sub-elements
24
25     ``.oe_list_add``
26
27         The default "Create"/"Add" button of the list view
28
29     ``.oe_alternative``
30
31         The "alternative choice" for the list view, by default text
32         along the lines of "or import" with a link.
33
34 ``.oe_list_field_cell``
35
36     The cell (``td``) for a given field of the list view, cells which
37     are *not* fields (e.g. name of a group, or number of items in a
38     group) will not have this class. The field cell can be further
39     specified:
40
41     ``.oe_number``
42
43         Numeric cell types (integer and float)
44
45     ``.oe_button``
46
47         Action button (``button`` tag in the view) inside the cell
48
49     ``.oe_readonly``
50
51         Readonly field cell
52
53     ``.oe_list_field_$type``
54
55         Additional class for the precise type of the cell, ``$type``
56         is the field's @widget if there is one, otherwise it's the
57         field's type.
58
59 ``.oe_list_record_selector``
60
61     Selector cells
62
63 Editable list view
64 ++++++++++++++++++
65
66 The editable list view module adds a few supplementary style hook
67 classes, for edition situations:
68
69 ``.oe_editing``
70
71     Added to both ``.oe_list`` and ``.oe_list_button`` (as the
72     buttons may be outside of the list view) when a row of the list is
73     currently being edited.
74
75 ``tr.oe_edition``
76
77     Class set on the row being edited itself. Note that the edition
78     form is *not* contained within the row, this allows for styling or
79     modifying the row while it's being edited separately. Mostly for
80     fields which can not be edited (e.g. read-only fields).
81
82
83 Editable list view
84 ------------------
85
86 List view edition is an extension to the base listview providing the
87 capability of inline record edition by delegating to an embedded form
88 view.
89
90 .. todo::
91
92     cleanup options and settings for editability configuration. Right
93     now there are:
94
95     ``defaults.editable``
96
97         ``null``, ``"top"`` or ``"bottom"``, generally broken and
98         useless
99
100     ``context.set_editable``
101
102         forces ``options.editable`` to ``"bottom"``
103
104     ``view.arch.attrs.editable``
105
106         same as ``defaults.editable``, but applied separately (after
107         reloading the view), if absent delegates to
108         ``options.editable`` which may have been set previously.
109
110     ``options.read_only``
111
112         force options.editable to false, or something?
113
114         .. note:: can probably be replaced by cancelling ``edit:before``
115
116     and :js:func:`~openerp.web.ListView.set_editable` which
117     ultimately behaves weird-as-fuck-ly.
118
119 The editable list view module adds a number of methods to the list
120 view, on top of implementing the :js:class:`EditorDelegate` protocol:
121
122 Interaction Methods
123 +++++++++++++++++++
124
125 .. js:function:: openerp.web.ListView.ensureSaved
126
127     Attempts to resolve the pending edition, if any, by saving the
128     edited row's current state.
129
130     :returns: delegate resolving to all editions having been saved, or
131               rejected if a pending edition could not be saved
132               (e.g. validation failure)
133
134 .. js:function:: openerp.web.ListView.startEdition([record])
135
136     Starts editing the provided record inline, through an overlay form
137     view of editable fields in the record.
138
139     If no record is provided, creates a new one according to the
140     editability configuration of the list view.
141
142     This method resolves any pending edition when invoked, before
143     starting a new edition.
144
145     :type record: :js:class:`~openerp.web.list.Record`
146     :returns: delegate to the form used for the edition
147
148 .. js:function:: openerp.web.ListView.saveEdition
149
150     Resolves the pending edition.
151
152     :returns: delegate to the save being completed, resolves to an
153               object with two attributes ``created`` (flag indicating
154               whether the saved record was just created or was
155               updated) and ``record`` the reloaded record having been
156               edited.
157
158 .. js:function:: openerp.web.ListView.cancelEdition
159
160     Cancels pending edition, cleans up the list view in case of
161     creation (removes the empty record being created).
162
163 Utility Methods
164 +++++++++++++++
165
166 .. js:function:: openerp.web.ListView.getCellsFor(row)
167
168     Extracts the cells from a listview row, and puts them in a
169     {fieldname: cell} mapping for analysis and manipulation.
170
171     :param jQuery row:
172     :rtype: Object
173
174 .. js:function:: openerp.web.ListView.withEvent(event_name, event, action[, args][, trigger_params])
175
176     Executes ``action`` in the context of the view's editor,
177     bracketing it with cancellable event signals.
178
179     :param String event_name: base name for the bracketing event, will
180                               be postfixed by ``:before`` and
181                               ``:after`` before being called
182                               (respectively before and after
183                               ``action`` is executed)
184     :param Object event: object passed to the ``:before`` event
185                          handlers.
186     :param Function action: function called with the view's editor as
187                             its ``this``. May return a deferred.
188     :param Array args: arguments passed to ``action``
189     :param Array trigger_params: arguments passed to the ``:after``
190                                  event handler alongside the results
191                                  of ``action``
192
193 Behavioral Customizations
194 +++++++++++++++++++++++++
195
196 .. js:function:: openerp.web.ListView.handleOnWrite(record)
197
198     Implements the handling of the ``onwrite`` listview attribute:
199     calls the RPC methods specified by ``@onwrite``, and if that
200     method returns an array of ids loads or reloads the records
201     corresponding to those ids.
202
203     :param record: record being written having triggered the
204                    ``onwrite`` callback
205     :type record: openerp.web.list.Record
206     :returns: deferred to all reloadings being done
207
208 Events
209 ++++++
210
211 For simpler interactions by/with external users of the listview, the
212 view provides a number of dedicated events to its lifecycle.
213
214 .. note:: if an event is defined as *cancellable*, it means its first
215           parameter is an object on which the ``cancel`` attribute can
216           be set. If the ``cancel`` attribute is set, the view will
217           abort its current behavior as soon as possible, and rollback
218           any state modification.
219
220 ``edit:before`` *cancellable*
221
222     Invoked before the list view starts editing a record.
223
224     Provided with an event object with a single property ``record``,
225     holding the attributes of the record being edited (``record`` is
226     empty *but not null* for a new record)
227
228 ``edit:after``
229
230     Invoked after the list view has gone into an edition state,
231     provided with the attributes of the record being edited (see
232     ``edit:before``) as first parameter and the form used for the
233     edition as second parameter.
234
235 ``save:before`` *cancellable*
236
237     Invoked right before saving a pending edition, provided with an
238     event object holding the listview's editor (``editor``) and the
239     edition form (``form``)
240
241 ``save:after``
242
243     Invoked after a save has been completed
244
245 ``cancel:before`` *cancellable*
246
247     Invoked before cancelling a pending edition, provided with the
248     same information as ``save:before``.
249
250 ``cancel:after``
251
252     Invoked after a pending edition has been cancelled.
253
254 DOM events
255 ++++++++++
256
257 The list view has grown hooks for the ``keyup`` event on its edition
258 form (during edition): any such event bubbling out of the edition form
259 will be forwarded to a method ``keyup_EVENTNAME``, where ``EVENTNAME``
260 is the name of the key in ``$.ui.keyCode``.
261
262 The method will also get the event object (originally passed to the
263 ``keyup`` handler) as its sole parameter.
264
265 The base editable list view has handlers for the ``ENTER`` and
266 ``ESCAPE`` keys.
267
268 Editor
269 ------
270
271 The list-edition modules does not generally interact with the embedded
272 formview, delegating instead to its
273 :js:class:`~openerp.web.list.Editor`.
274
275 .. js:class:: openerp.web.list.Editor(parent[, options])
276
277     The editor object provides a more convenient interface to form
278     views, and simplifies the usage of form views for semi-arbitrary
279     edition of stuff.
280
281     However, the editor does *not* task itself with being internally
282     consistent at this point: calling
283     e.g. :js:func:`~openerp.web.list.Editor.edit` multiple times in a
284     row without saving or cancelling each edit is undefined.
285
286     :param parent:
287     :type parent: :js:class:`~openerp.web.Widget`
288     :param EditorOptions options:
289
290     .. js:function:: openerp.web.list.Editor.isEditing
291
292         Indicates whether the editor is currently in the process of
293         providing edition for a field.
294
295         :rtype: Boolean
296
297     .. js:function:: openerp.web.list.Editor.edit(record, configureField)
298
299         Loads the provided record into the internal form view and
300         displays the form view.
301
302         Will also attempt to focus the first visible field of the form
303         view.
304
305         :param Object record: record to load into the form view
306                               (key:value mapping similar to the result
307                               of a ``read``)
308         :param configureField: function called with each field of the
309                                form view right after the form is
310                                displayed, lets whoever called this
311                                method do some last-minute
312                                configuration of form fields.
313         :type configureField: Function<String, openerp.web.form.Field>
314         :returns: jQuery delegate to the form object
315
316     .. js:function:: openerp.web.list.Editor.save
317
318         Attempts to save the internal form, then hide it
319
320         :returns: delegate to the record under edition (with ``id``
321                   added for a creation). The record is not updated
322                   from when it was passed in, aside from the ``id``
323                   attribute.
324
325     .. js:function:: openerp.web.list.Editor.cancel
326
327         Attemps to cancel the edition of the internal form, then hide
328         the form
329
330         :returns: delegate to the record under edition
331
332 .. js:class:: EditorOptions
333
334     .. js:attribute:: EditorOptions.formView
335
336         Form view (sub)-class to instantiate and delegate edition to.
337
338         By default, :js:class:`~openerp.web.FormView`
339
340     .. js:attribute:: EditorOptions.delegate
341
342         Object used to get various bits of information about how to
343         display stuff.
344
345         By default, uses the editor's parent widget. See
346         :js:class:`EditorDelegate` for the methods and attributes to
347         provide.
348
349 .. js:class:: EditorDelegate
350
351     Informal protocol defining the methods and attributes expected of
352     the :js:class:`~openerp.web.list.Editor`'s delegate.
353
354     .. js:attribute:: EditorDelegate.dataset
355
356         The dataset passed to the form view to synchronize the form
357         view and the outer widget.
358
359     .. js:function:: EditorDelegate.editionView(editor)
360
361         Called by the :js:class:`~openerp.web.list.Editor` object to
362         get a form view (JSON) to pass along to the form view it
363         created.
364
365         The result should be a valid form view, see :doc:`Form Notes
366         <form-notes>` for various peculiarities of the form view
367         format.
368
369         :param editor: editor object asking for the view
370         :type editor: :js:class:`~openerp.web.list.Editor`
371         :returns: form view
372         :rtype: Object
373
374     .. js:function:: EditorDelegate.isPrependOnCreate
375
376         By default, the :js:class:`~openerp.web.list.Editor` will
377         append the ids of newly created records to the
378         :js:attr:`EditorDelegate.dataset`. If this method returns
379         ``true``, it will prepend these ids instead.
380
381         :returns: whether new records should be prepended to the
382                   dataset (instead of appended)
383         :rtype: Boolean
384
385 Changes from 6.1
386 ----------------
387
388 * The editable listview behavior has been rewritten pretty much from
389   scratch, any code touching on editability will have to be modified
390
391   * The overloading of :js:class:`~openerp.web.ListView.Groups` and
392     :js:class:`~openerp.web.ListView.List` for editability has been
393     drastically simplified, and most of the behavior has been moved to
394     the list view itself. Only
395     :js:func:`~openerp.web.ListView.List.row_clicked` is still
396     overridden.
397
398   * A new method ``getRowFor(record) -> jQuery(tr) | null`` has been
399     added to both ListView.List and ListView.Group, it can be called
400     from the list view to get the table row matching a record (if such
401     a row exists).
402
403 * ``ListView#ensure_saved`` has been re-capitalized to
404   :js:func:`~openerp.web.ListView.ensureSaved`
405
406 * :js:func:`~openerp.web.ListView.do_button_action`'s core behavior
407   has been split away to
408   :js:func:`~openerp.web.ListView.handleButton`. This allows bypassing
409   overrides of :js:func:`~openerp.web.ListView.do_button_action` in a
410   parent class.
411
412   Ideally, :js:func:`~openerp.web.ListView.handleButton` should not be
413   overridden.
414
415 * Modifiers handling has been improved (all modifiers information
416   should now be available through :js:func:`~Column.modifiers_for`,
417   not just ``invisible``)
418
419 * Changed some handling of the list view's record: a record may now
420   have no id, and the listview will handle that correctly (for new
421   records being created) as well as correctly handle the ``id`` being
422   set.
423
424 * Extended the internal collections structure of the list view with
425   `#find`_, `#succ`_ and `#pred`_.
426
427 .. _#find: http://underscorejs.org/#find
428
429 .. _#succ: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:succ
430
431 .. _#pred: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:pred