summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js
diff options
context:
space:
mode:
authorJulien Mougenot <jum@odoo.com>2019-09-06 12:33:28 +0000
committerAaron Bohy <aab@odoo.com>2019-09-18 11:31:43 +0000
commitff9a0b87e63fd7d2b38514d21a52cbad7702582d (patch)
treec0dc09777b21f8fcf86fd2ff1fb9969ff97efbdf /addons/web/static/src/js
parent708a5b656618e1bcc8034bd7feddfcb5aac6a998 (diff)
[FIX] web: list: m2o doesn't trigger fieldChange when empty
Gives time to the user to enter an actual value in m2o in list views. Before this commit, emptying a many2one field (selecting all > BACKSPACE or DELETE) triggered instantly a field_change. This was an issue in multi edition as a field changed triggered instantly a save on selected records without giving time to the user to enter a new value. Now, many2ones only trigger a fieldChange when selecting a new valid value. Task 2068280
Diffstat (limited to 'addons/web/static/src/js')
-rw-r--r--addons/web/static/src/js/fields/relational_fields.js78
-rw-r--r--addons/web/static/src/js/views/view_dialogs.js5
2 files changed, 79 insertions, 4 deletions
diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js
index f713342c240..1646ef735a2 100644
--- a/addons/web/static/src/js/fields/relational_fields.js
+++ b/addons/web/static/src/js/fields/relational_fields.js
@@ -397,8 +397,10 @@ var FieldMany2One = AbstractField.extend({
kanban_view_ref: this.attrs.kanban_view_ref,
on_selected: function (records) {
self.reinitialize(records[0]);
+ },
+ on_closed: function () {
self.activate();
- }
+ },
};
},
/**
@@ -650,7 +652,6 @@ var FieldMany2One = AbstractField.extend({
* in the dialog (each filter has keys 'description' and 'domain')
*/
_searchCreatePopup: function (view, ids, context, dynamicFilters) {
- var self = this;
var options = this._getSearchCreatePopupOptions(view, ids, context, dynamicFilters);
return new dialogs.SelectCreateDialog(this, _.extend({}, this.nodeOptions, options)).open();
},
@@ -820,6 +821,23 @@ var Many2oneBarcode = FieldMany2One.extend({
});
var ListFieldMany2One = FieldMany2One.extend({
+ events: _.extend({}, FieldMany2One.prototype.events, {
+ 'focusin input': '_onInputFocusin',
+ }),
+
+ /**
+ * @override
+ */
+ init: function () {
+ this._super.apply(this, arguments);
+ // when we empty the input, we delay the setValue to prevent from
+ // triggering the 'fieldChanged' event twice when the user wants set
+ // another m2o value ; the following attribute is used to determine when
+ // we skipped the setValue, s.t. we can perform it later on if the user
+ // didn't select another value
+ this.mustSetValue = false;
+ this.m2oDialogFocused = false;
+ },
//--------------------------------------------------------------------------
// Public
@@ -836,6 +854,13 @@ var ListFieldMany2One = FieldMany2One.extend({
}
return this._super.apply(this, arguments);
},
+ /**
+ * @override
+ */
+ reinitialize: function () {
+ this.mustSetValue = false;
+ return this._super.apply(this, arguments);
+ },
//--------------------------------------------------------------------------
// Private
@@ -847,6 +872,52 @@ var ListFieldMany2One = FieldMany2One.extend({
_renderReadonly: function () {
this.$el.text(this.m2o_value);
},
+ /**
+ * @override
+ * @private
+ */
+ _searchCreatePopup: function () {
+ this.m2oDialogFocused = true;
+ return this._super.apply(this, arguments);
+ },
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ _onInputFocusin: function () {
+ this.m2oDialogFocused = false;
+ },
+ /**
+ * In list views, we don't want to try to trigger a fieldChange when the field
+ * is being emptied. Instead, it will be triggered as the user leaves the field
+ * while it is empty.
+ *
+ * @override
+ * @private
+ */
+ _onInputFocusout: function () {
+ this._super.apply(this, arguments);
+ if (!this.m2oDialogFocused && this.$input.val() === "" && this.mustSetValue) {
+ this.reinitialize(false);
+ }
+ },
+ /**
+ * Prevents the triggering of an immediate _onFieldChanged when emptying the field.
+ *
+ * @override
+ * @private
+ */
+ _onInputKeyup: function () {
+ if (this.$input.val() !== "") {
+ this._super.apply(this, arguments);
+ } else {
+ this.mustSetValue = true;
+ }
+ },
});
var KanbanFieldMany2One = AbstractField.extend({
@@ -2220,8 +2291,7 @@ var FieldMany2ManyTags = AbstractField.extend({
disable_multiple_selection: false,
on_selected: function (records) {
self.many2one.reinitialize(records);
- self.many2one.activate();
- }
+ },
});
};
return this.many2one.appendTo(this.$el);
diff --git a/addons/web/static/src/js/views/view_dialogs.js b/addons/web/static/src/js/views/view_dialogs.js
index 130173a16fc..47e3a5309d9 100644
--- a/addons/web/static/src/js/views/view_dialogs.js
+++ b/addons/web/static/src/js/views/view_dialogs.js
@@ -320,6 +320,7 @@ var SelectCreateDialog = ViewDialog.extend({
this._super.apply(this, arguments);
_.defaults(this.options, { initial_view: 'search' });
this.on_selected = this.options.on_selected || (function () {});
+ this.on_closed = this.options.on_closed || (function () {});
this.initialIDs = this.options.initial_ids;
this.viewType = 'list';
},
@@ -395,6 +396,10 @@ var SelectCreateDialog = ViewDialog.extend({
return fragment;
});
},
+ close: function () {
+ this._super.apply(this, arguments);
+ this.on_closed();
+ },
create_edit_record: function () {
var self = this;
var dialog = new FormViewDialog(this, _.extend({}, this.options, {