summaryrefslogtreecommitdiff
path: root/addons/web
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web')
-rw-r--r--addons/web/static/src/js/fields/abstract_field.js17
-rw-r--r--addons/web/static/src/js/fields/abstract_field_owl.js17
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js2
-rw-r--r--addons/web/static/tests/fields/basic_fields_tests.js48
4 files changed, 77 insertions, 7 deletions
diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js
index ab6f226a66e..16e928ea288 100644
--- a/addons/web/static/src/js/fields/abstract_field.js
+++ b/addons/web/static/src/js/fields/abstract_field.js
@@ -404,6 +404,18 @@ var AbstractField = Widget.extend({
return `text-${decoration.split('-')[1]}`;
},
/**
+ * Compares the given value with the last value that has been set.
+ * Note that we compare unparsed values. Handles the special case where no
+ * value has been set yet, and the given value is the empty string.
+ *
+ * @private
+ * @param {any} value
+ * @returns {boolean} true iff values are the same
+ */
+ _isLastSetValue: function (value) {
+ return this.lastSetValue === value || (this.value === false && value === '');
+ },
+ /**
* This method check if a value is the same as the current value of the
* field. For example, a fieldDate widget might want to use the moment
* specific value isSame instead of ===.
@@ -499,9 +511,8 @@ var AbstractField = Widget.extend({
* @returns {Promise}
*/
_setValue: function (value, options) {
- // we try to avoid doing useless work, if the value given has not
- // changed. Note that we compare the unparsed values.
- if (this.lastSetValue === value || (this.value === false && value === '')) {
+ // we try to avoid doing useless work, if the value given has not changed.
+ if (this._isLastSetValue(value)) {
return Promise.resolve();
}
this.lastSetValue = value;
diff --git a/addons/web/static/src/js/fields/abstract_field_owl.js b/addons/web/static/src/js/fields/abstract_field_owl.js
index f97faae35ed..43e3d468d78 100644
--- a/addons/web/static/src/js/fields/abstract_field_owl.js
+++ b/addons/web/static/src/js/fields/abstract_field_owl.js
@@ -454,6 +454,18 @@ odoo.define('web.AbstractFieldOwl', function (require) {
return `text-${decoration.split('-')[1]}`;
}
/**
+ * Compares the given value with the last value that has been set.
+ * Note that we compare unparsed values. Handles the special case where no
+ * value has been set yet, and the given value is the empty string.
+ *
+ * @private
+ * @param {any} value
+ * @returns {boolean} true iff values are the same
+ */
+ _isLastSetValue(value) {
+ return this._lastSetValue === value || (this.value === false && value === '');
+ }
+ /**
* This method check if a value is the same as the current value of the
* field. For example, a fieldDate component might want to use the moment
* specific value isSame instead of ===.
@@ -498,9 +510,8 @@ odoo.define('web.AbstractFieldOwl', function (require) {
* @returns {Promise}
*/
_setValue(value, options) {
- // we try to avoid doing useless work, if the value given has not
- // changed. Note that we compare the unparsed values.
- if (this._lastSetValue === value || (this.value === false && value === '')) {
+ // we try to avoid doing useless work, if the value given has not changed.
+ if (this._isLastSetValue(value)) {
return Promise.resolve();
}
this._lastSetValue = value;
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index bf225d7ea99..d5f1f1074d4 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -326,7 +326,7 @@ var InputField = DebouncedField.extend({
* @private
*/
_onInput: function () {
- this.isDirty = true;
+ this.isDirty = !this._isLastSetValue(this.$input.val());
this._doDebouncedAction();
},
/**
diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js
index c7040a98744..3d98ea984e7 100644
--- a/addons/web/static/tests/fields/basic_fields_tests.js
+++ b/addons/web/static/tests/fields/basic_fields_tests.js
@@ -1743,6 +1743,54 @@ QUnit.module('basic_fields', {
form.destroy();
});
+ QUnit.test('input field: set and remove value, then wait for onchange', async function (assert) {
+ assert.expect(2);
+
+ this.data.partner.onchanges = {
+ product_id(obj) {
+ obj.foo = obj.product_id ? "onchange value" : false;
+ },
+ };
+
+ let def;
+ const form = await createView({
+ View: FormView,
+ model: 'partner',
+ data: this.data,
+ arch: `
+ <form>
+ <field name="p">
+ <tree editable="bottom">
+ <field name="product_id"/>
+ <field name="foo"/>
+ </tree>
+ </field>
+ </form>`,
+ async mockRPC(route, args) {
+ const result = this._super(...arguments);
+ if (args.method === "onchange") {
+ await Promise.resolve(def);
+ }
+ return result;
+ },
+ fieldDebounce: 1000, // needed to accurately mock what really happens
+ });
+
+ await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a'));
+ assert.strictEqual(form.$('input[name="foo"]').val(), "");
+
+ await testUtils.fields.editInput(form.$('input[name="foo"]'), "test"); // set value for foo
+ await testUtils.fields.editInput(form.$('input[name="foo"]'), ""); // remove value for foo
+
+ // trigger the onchange by setting a product
+ await testUtils.fields.many2one.clickOpenDropdown('product_id');
+ await testUtils.fields.many2one.clickHighlightedItem('product_id');
+ assert.strictEqual(form.$('input[name="foo"]').val(), 'onchange value',
+ 'input should contain correct value after onchange');
+
+ form.destroy();
+ });
+
QUnit.module('UrlWidget');
QUnit.test('url widget in form view', async function (assert) {