diff options
| author | Christophe Simonis <chs@odoo.com> | 2017-08-02 12:31:05 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2017-08-02 12:31:05 +0200 |
| commit | fcfb4782b6d93348bd2028fef9da335f6a953c05 (patch) | |
| tree | 2705dbbf0deabf19c80faae27ed15eb47883b04d /addons/web/static/src/js/fields | |
| parent | c1d22b6c3c605d894130251c4417b684d7cf1b54 (diff) | |
| parent | a445548f07fbf8d883f4b02e18a35f4b324c6961 (diff) | |
[MERGE] forward port branch saas-17 up to a445548f07f
Diffstat (limited to 'addons/web/static/src/js/fields')
| -rw-r--r-- | addons/web/static/src/js/fields/abstract_field.js | 14 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/basic_fields.js | 33 | ||||
| -rw-r--r-- | addons/web/static/src/js/fields/relational_fields.js | 32 |
3 files changed, 51 insertions, 28 deletions
diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js index fa2f37a123f..9b484354544 100644 --- a/addons/web/static/src/js/fields/abstract_field.js +++ b/addons/web/static/src/js/fields/abstract_field.js @@ -65,12 +65,10 @@ var AbstractField = Widget.extend({ * @constructor * @param {Widget} parent * @param {string} name The field name defined in the model - * @param {Object} record A record object (result of the get method of + * @param {Object} record A record object (result of the get method of * a basic model) * @param {Object} [options] * @param {string} [options.mode=readonly] should be 'readonly' or 'edit' - * @param {string} [options.standalone=false] this flag indicates that the - * field does not have a controller to delegate to */ init: function (parent, name, record, options) { this._super(parent); @@ -160,10 +158,6 @@ var AbstractField = Widget.extend({ // calls to the format (resp. parse) function. this.formatOptions = {}; this.parseOptions = {}; - - // standalone is a flag indicating that the field does not have a - // controller to delegate actions to - this.standalone = options.standalone; }, /** * When a field widget is appended to the DOM, its start method is called, @@ -379,6 +373,11 @@ var AbstractField = Widget.extend({ * @private * @param {any} value * @param {Object} [options] + * @param {boolean} [options.doNotSetDirty=false] if true, the basic model + * will not consider that this field is dirty, even though it was changed. + * Please do not use this flag unless you really need it. Our only use + * case is currently the pad widget, which does a _setValue in the + * renderEdit method. * @param {boolean} [options.forceChange=false] if true, the change event will be * triggered even if the new value is the same as the old one * @returns {Deferred} @@ -407,6 +406,7 @@ var AbstractField = Widget.extend({ dataPointID: this.dataPointID, changes: changes, viewType: this.viewType, + doNotSetDirty: options && options.doNotSetDirty, onSuccess: def.resolve.bind(def), onFailure: def.reject.bind(def), }); diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 2f41f81f932..2de5a73802d 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -151,6 +151,9 @@ var DebouncedField = AbstractField.extend({ }); var InputField = DebouncedField.extend({ + custom_events: _.extend({}, DebouncedField.prototype.custom_events, { + field_changed: '_onFieldChanged', + }), events: _.extend({}, DebouncedField.prototype.events, { 'input': '_onInput', 'change': '_onChange', @@ -168,6 +171,12 @@ var InputField = DebouncedField.extend({ if (this.mode === 'edit') { this.tagName = 'input'; } + // 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; }, //-------------------------------------------------------------------------- @@ -183,14 +192,21 @@ var InputField = DebouncedField.extend({ return this.$input || $(); }, /** - * Do not re-render this field if it was the origin of the onchange call. - * FIXME: make the onchange work on itself without disturbing the user typing + * 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.target === this) { + if (!event || event === this.lastChangeEvent) { + this.isDirty = false; + } + if (this.isDirty || (event && event.target === this)) { return $.when(); } else { return this._render(); @@ -266,6 +282,16 @@ var InputField = DebouncedField.extend({ this._doAction(); }, /** + * 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; + }, + /** * Called when the user is typing text -> By default this only calls a * debounced method to notify the outside world of the changes. * @see _doDebouncedAction @@ -273,6 +299,7 @@ var InputField = DebouncedField.extend({ * @private */ _onInput: function () { + this.isDirty = true; this._doDebouncedAction(); }, /** diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 1935e5804dd..64049d8b1ec 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -223,25 +223,21 @@ var FieldMany2One = AbstractField.extend({ _quickCreate: function (name) { var self = this; var slowCreate = this._searchCreatePopup.bind(this, "form", false, this._createContext(name)); - var action = function () { - return self._rpc({ - model: self.field.relation, - method: 'name_create', - args: [name], - context: self.record.getContext(self.recordParams), - }).then(function (result) { - if (self.mode === "edit") { - self.reinitialize({id: result[0], display_name: result[1]}); - } - }, slowCreate); - }; - if (this.nodeOptions.quick_create) { - if (this.standalone) { - action(); - } else { - this.trigger_up('mutexify', {action: action}); - } + this.trigger_up('mutexify', { + action: function () { + return self._rpc({ + model: self.field.relation, + method: 'name_create', + args: [name], + context: self.record.getContext(self.recordParams), + }).then(function (result) { + if (self.mode === "edit") { + self.reinitialize({id: result[0], display_name: result[1]}); + } + }, slowCreate); + }, + }); } else { slowCreate(); } |
