diff options
| author | Aaron Bohy <aab@odoo.com> | 2017-06-16 15:44:43 +0200 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2017-06-27 14:12:31 +0200 |
| commit | 17e198153ecfd9c5c32b3b22f43e2f1b8100a1c3 (patch) | |
| tree | 69fa5787861316efdffd38a1f5b342fcb5cd13bc /addons/web/static/src/js/fields | |
| parent | 278e478d55209bd958836fde7fe1c82c555180dc (diff) | |
[FIX] web: BasicModel: store changes in x2many as operations
Datapoints of the BasicModel store the data fetched from the
server and changes done (not saved yet) by the user. For x2many
fields, datapoints are of type 'list' and have a 'res_ids' key
containing the ids of all records in the relation. They also have a
'data' key containing datapoints of type 'record', representing the
records in the relation that have been fetched (with a limit set to
40 or 80 depending on the subview used). So basically, the length
of res_ids may be different than the length of data.
Before this rev., the changes in x2manys were saved under the key
'_changes' as a duplication of the content of 'data', i.e. same
list of datapoints of type 'record', modulo the changes done (it
contained the new records added and didn't contained the removed
records, whereas the 'data' remained unchanged). This didn't worked
at all when there were more records than the limit in the relation.
Indeed, when this happened, the commands to send to the server
couldn't be generated correctly.
This rev. modifies the way changes are stored in those datapoints.
Now, each change is stored as an operation. An operation could be
of type 'ADD', 'REMOVE', 'REMOVE_ALL' or 'UPDATE'. As before,
'data' remains unchanged and always keeps the datapoints of records
that have been fetched (the ones that are currently displayed in
the list or kanban subview). This way, commands can now be properly
computed.
This had a nice side-effect of fixing two other bugs linked to
x2manys.
First, when used in a context (e.g. {some_key: some_x2many_field}),
the value of some_x2many_field (i.e. a list of commands) was always
[] if the field was invisible="1" in the view, because it's
subrecords weren't fetched, and the generated commands were based
on them. Now, they are generated from the list of res_ids in the
relation, so it works fine.
Second, the x2many records are supposed to be sorted client-side,
after being read, and after each edition. This was working in the
first case, but not in the second. Now it's working even after
a record edition.
This rev. also correctly sets the 'parentID' and 'static' keys in
datapoints.
Finally, we also fixed the pager in x2manys as it was badly
displayed (small less tweaks).
Diffstat (limited to 'addons/web/static/src/js/fields')
| -rw-r--r-- | addons/web/static/src/js/fields/relational_fields.js | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 419d1f5f646..5b9114b6c82 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -657,7 +657,14 @@ var FieldX2Many = AbstractField.extend({ reset: function (record, ev) { if (ev && ev.target === this && ev.data.changes && this.view.arch.tag === 'tree') { var command = ev.data.changes[this.name]; - if (command.operation === 'UPDATE') { + // Here, we only consider 'UPDATE' commands with data, which occur + // with editable list view. In order to keep the current line in + // edition, we call confirmChange which will reset the widgets + // instead of re-rendering the list. 'UPDATE' commands with no data + // can be ignored: they occur in one2manys when the record is + // updated from a dialog and in this case, we can re-render the + // whole subview. + if (command.operation === 'UPDATE' && command.data) { var state = record.data[this.name]; var fieldNames = state.getFieldNames(); this.renderer.confirmChange(state, command.id, fieldNames, ev.initialEvent); @@ -1068,9 +1075,15 @@ var FieldOne2Many = FieldX2Many.extend({ // we don't want interference with the components upstream. ev.stopPropagation(); + var id = ev.data.id; + // trigger an empty 'UPDATE' operation when the user clicks on 'Save' in + // the dialog, to notify the main record that a subrecord of this + // relational field has changed (those changes will be already stored on + // that subrecord, thanks to the 'Save'). + var onSaved = this._setValue.bind(this, { operation: 'UPDATE', id: id }, {}); this._openFormDialog({ - id: ev.data.id, - on_saved: this._setValue.bind(this, { operation: 'NOOP' }, {}), + id: id, + on_saved: onSaved, readonly: this.mode === 'readonly', }); }, |
