diff options
| author | Aaron Bohy <aab@odoo.com> | 2017-05-19 10:13:24 +0200 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2017-05-19 15:51:57 +0200 |
| commit | c929a81e8f015f9234f68749a29fe6a9c21577b6 (patch) | |
| tree | 4471550e5f2c70ffe75137d3fc272f97a8e25ef8 /addons/web/static/src/js/fields | |
| parent | a845ecffa13657922ba75dbc7f37c7bad8c0e4c0 (diff) | |
[FIX] web: DebounceField: do nothing after widget destruction
DebounceFields debounce the function that notify field changes to
their environment (using _.debounce). It may happen that this
function is called once the field widget is destroyed (e.g.
type something in a char field and quickly click on Save, the
function is called directly by _commitChanges, but the debounced
call is still pending). It may be a problem if the subsequent
code does something like this.getSession().some_key, as if the
widget is destroyed, it has no parent that can provide it the
session, and thus it crashes.
Also rename attribute _debouncedStarted into _isDirty as it makes
much more sense.
Diffstat (limited to 'addons/web/static/src/js/fields')
| -rw-r--r-- | addons/web/static/src/js/fields/basic_fields.js | 16 |
1 files changed, 11 insertions, 5 deletions
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index b35b84fe6ee..3f279eeeec7 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -83,10 +83,10 @@ var DebouncedField = AbstractField.extend({ init: function () { this._super.apply(this, arguments); - // _debouncedStarted is used to detect that the user interacted at least + // _isDirty is used to detect that the user interacted at least // once with the widget, so that we can prevent it from triggering a // field_changed in commitChanges if the user didn't change anything - this._debouncedStarted = false; + this._isDirty = false; if (this.mode === 'edit') { if (this.DEBOUNCE) { this._doDebouncedAction = _.debounce(this._doAction, this.DEBOUNCE); @@ -97,7 +97,7 @@ var DebouncedField = AbstractField.extend({ var self = this; var debouncedFunction = this._doDebouncedAction; this._doDebouncedAction = function () { - self._debouncedStarted = true; + self._isDirty = true; debouncedFunction.apply(self, arguments); }; } @@ -115,7 +115,7 @@ var DebouncedField = AbstractField.extend({ * @override */ commitChanges: function () { - if (this._debouncedStarted && this.mode === 'edit') { + if (this._isDirty && this.mode === 'edit') { this._doAction(); } }, @@ -132,7 +132,13 @@ var DebouncedField = AbstractField.extend({ * @private */ _doAction: function () { - this._setValue(this._getValue()); + // as _doAction may be debounced, it may happen that it is called after + // the widget has been destroyed, and in this case, we don't want it to + // do anything (commitChanges ensures that if it has local changes, they + // are triggered up before the widget is destroyed, if necessary). + if (!this.isDestroyed()) { + this._setValue(this._getValue()); + } }, /** * Should return the current value of the field, in the DOM (for example, |
