summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js41
-rw-r--r--addons/web/static/src/js/views/basic/basic_model.js31
2 files changed, 58 insertions, 14 deletions
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index 6f775e789d4..9cdadb1051a 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -95,6 +95,7 @@ var FieldMany2One = AbstractField.extend({
template: 'FieldMany2One',
custom_events: _.extend({}, AbstractField.prototype.custom_events, {
'closed_unset': '_onDialogClosedUnset',
+ 'field_changed': '_onFieldChanged',
'quick_create': '_onQuickCreate',
'search_create_popup': '_onSearchCreatePopup',
}),
@@ -124,6 +125,12 @@ var FieldMany2One = AbstractField.extend({
// 'recordParams' is a dict of params used when calling functions
// 'getDomain' and 'getContext' on this.record
this.recordParams = {fieldName: this.name, viewType: this.viewType};
+ // We need to know if the widget is dirty (i.e. if the user has changed
+ // the value, and those changes haven't been acknowledged yet by the
+ // environment), to prevent erasing that new value on a reset (e.g.
+ // coming by an onchange on another field)
+ this.isDirty = false;
+ this.lastChangeEvent = undefined;
},
start: function () {
// booleean indicating that the content of the input isn't synchronized
@@ -151,9 +158,31 @@ var FieldMany2One = AbstractField.extend({
* TODO
*/
reinitialize: function (value) {
+ this.isDirty = false;
this.floating = false;
this._setValue(value);
},
+ /**
+ * Re-renders the widget if it isn't dirty. The widget is dirty if the user
+ * changed the value, and that change hasn't been acknowledged yet by the
+ * environment. For example, another field with an onchange has been updated
+ * and this field is updated before the onchange returns. Two '_setValue'
+ * are done (this is sequential), the first one returns and this widget is
+ * reset. However, it has pending changes, so we don't re-render.
+ *
+ * @override
+ */
+ reset: function (record, event) {
+ this._reset(record, event);
+ if (!event || event === this.lastChangeEvent) {
+ this.isDirty = false;
+ }
+ if (this.isDirty) {
+ return $.when();
+ } else {
+ return this._render();
+ }
+ },
//--------------------------------------------------------------------------
// Private
@@ -238,6 +267,16 @@ var FieldMany2One = AbstractField.extend({
return value.split('\n')[0];
},
/**
+ * Listens to events 'field_changed' to keep track of the last event that
+ * has been trigerred. This allows to detect that all changes have been
+ * acknowledged by the environment.
+ *
+ * @param {OdooEvent} event 'field_changed' event
+ */
+ _onFieldChanged: function (event) {
+ this.lastChangeEvent = event;
+ },
+ /**
* @private
* @param {string} name
* @returns {Deferred} resolved after the name_create or when the slowcreate
@@ -476,6 +515,7 @@ var FieldMany2One = AbstractField.extend({
* @private
*/
_onDialogClosedUnset: function () {
+ this.isDirty = false;
this.floating = false;
this._render();
},
@@ -544,6 +584,7 @@ var FieldMany2One = AbstractField.extend({
// confirmation that the many2one is not properly set.
return;
}
+ this.isDirty = true;
if (this.$input.val() === "") {
this.reinitialize(false);
} else if (this._getDisplayName(this.m2o_value) !== this.$input.val()) {
diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js
index c16f635a604..39f1be0d107 100644
--- a/addons/web/static/src/js/views/basic/basic_model.js
+++ b/addons/web/static/src/js/views/basic/basic_model.js
@@ -1495,7 +1495,8 @@ var BasicModel = AbstractModel.extend({
def = this._rpc({
model: list.model,
method: 'read',
- args: [_.pluck(data, 'id'), fieldNames]
+ args: [_.pluck(data, 'id'), fieldNames],
+ context: record.context,
}).then(function (records) {
_.each(records, function (record) {
list_records[record.id].data = record;
@@ -1743,22 +1744,21 @@ var BasicModel = AbstractModel.extend({
/**
* Fetch all name_gets for the many2ones in a group
*
- * @param {Object} group a valid resource object
+ * @param {Object[]} groups a list of object with context and record sub keys
* @returns {Deferred}
*/
- _fetchMany2OneGroup: function (group) {
- var ids = _.uniq(_.pluck(group, 'res_id'));
-
+ _fetchMany2OneGroup: function (groups) {
+ var ids = _.uniq(_.pluck(_.pluck(groups, 'record'), 'res_id'));
return this._rpc({
- model: group[0].model,
+ model: groups[0].record.model,
method: 'name_get',
args: [ids],
- context: group[0].context
+ context: groups[0].context
})
.then(function (name_gets) {
- _.each(group, function (record) {
- var nameGet = _.find(name_gets, function (n) { return n[0] === record.res_id;});
- record.data.display_name = nameGet[1];
+ _.each(groups, function (obj) {
+ var nameGet = _.find(name_gets, function (n) { return n[0] === obj.record.res_id;});
+ obj.record.data.display_name = nameGet[1];
});
});
},
@@ -2019,14 +2019,17 @@ var BasicModel = AbstractModel.extend({
if (!relatedRecord) {
return;
}
- toBeFetched.push(relatedRecord);
+ toBeFetched.push({
+ context: record.getContext({fieldName: name, viewType: record.viewType}),
+ record: relatedRecord
+ });
}
});
// group them by model and context. Using the context as key is
// necessary to make sure the correct context is used for the rpc;
- var groups = _.groupBy(toBeFetched, function (rec) {
- return [rec.model, JSON.stringify(rec.context)].join();
+ var groups = _.groupBy(toBeFetched, function (elem) {
+ return [elem.record.model, JSON.stringify(elem.context)].join();
});
return $.when.apply($, _.map(groups, this._fetchMany2OneGroup.bind(this)));
@@ -2416,7 +2419,7 @@ var BasicModel = AbstractModel.extend({
model: field.relation,
method: 'read',
args: [ids, fieldNames],
- context: {}, // FIXME
+ context: list.getContext() || {},
});
} else {
def = $.when(_.map(ids, function (id) {