diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 325e0ceb8e8..398928f585b 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -376,6 +376,29 @@ var FieldMany2One = AbstractField.extend({ _getDisplayName: function (value) { return value.split('\n')[0]; }, + /** + * Prepares and returns options for SelectCreateDialog + * + * @private + */ + _getSearchCreatePopupOptions: function(view, ids, context, dynamicFilters) { + var self = this; + return { + res_model: this.field.relation, + domain: this.record.getDomain({fieldName: this.name}), + context: _.extend({}, this.record.getContext(this.recordParams), context || {}), + dynamicFilters: dynamicFilters || [], + title: (view === 'search' ? _t("Search: ") : _t("Create: ")) + this.string, + initial_ids: ids, + initial_view: view, + disable_multiple_selection: true, + no_create: !self.can_create, + on_selected: function (records) { + self.reinitialize(records[0]); + self.activate(); + } + }; + }, /** * 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 @@ -613,21 +636,8 @@ var FieldMany2One = AbstractField.extend({ */ _searchCreatePopup: function (view, ids, context, dynamicFilters) { var self = this; - return new dialogs.SelectCreateDialog(this, _.extend({}, this.nodeOptions, { - res_model: this.field.relation, - domain: this.record.getDomain({fieldName: this.name}), - context: _.extend({}, this.record.getContext(this.recordParams), context || {}), - dynamicFilters: dynamicFilters || [], - title: (view === 'search' ? _t("Search: ") : _t("Create: ")) + this.string, - initial_ids: ids, - initial_view: view, - disable_multiple_selection: true, - no_create: !self.can_create, - on_selected: function (records) { - self.reinitialize(records[0]); - self.activate(); - } - })).open(); + var options = this._getSearchCreatePopupOptions(view, ids, context, dynamicFilters); + return new dialogs.SelectCreateDialog(this, _.extend({}, this.nodeOptions, options)).open(); }, /** * @private @@ -2119,6 +2129,19 @@ var FieldMany2ManyTags = AbstractField.extend({ this.many2one._getSearchBlacklist = function () { return self.value.res_ids; }; + var _getSearchCreatePopupOptions = this.many2one._getSearchCreatePopupOptions; + this.many2one._getSearchCreatePopupOptions = function (view, ids, context, dynamicFilters) { + var options = _getSearchCreatePopupOptions.apply(this, arguments); + var domain = this.record.getDomain({fieldName: this.name}); + return _.extend({}, options, { + domain: domain.concat(["!", ["id", "in", self.value.res_ids]]), + 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/tests/fields/relational_fields/field_many2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js index e20ad604c98..cf19fe30fe6 100644 --- a/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_many2many_tests.js @@ -1022,6 +1022,85 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('many2many tags widget: select multiple records', async function (assert) { + assert.expect(5); + for (var i = 1; i <= 10; i++) { + this.data.partner_type.records.push({ id: 100 + i, display_name: "Partner" + i}); + } + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + res_id: 1, + archs: { + 'partner_type,false,list': '