summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/views/form_relational_widgets.js462
-rw-r--r--addons/web/static/src/xml/base.xml4
2 files changed, 231 insertions, 235 deletions
diff --git a/addons/web/static/src/js/views/form_relational_widgets.js b/addons/web/static/src/js/views/form_relational_widgets.js
index 4876440e4f6..17f6cd842c9 100644
--- a/addons/web/static/src/js/views/form_relational_widgets.js
+++ b/addons/web/static/src/js/views/form_relational_widgets.js
@@ -16,7 +16,7 @@ var ViewManager = require('web.ViewManager');
var _t = core._t;
var QWeb = core.qweb;
-var commands = common.commands;
+var COMMANDS = common.commands;
var list_widget_registry = core.list_widget_registry;
var M2ODialog = Dialog.extend({
@@ -498,103 +498,222 @@ var AddAnItemList = ListView.List.extend({
/**
* A Abstract field for one2many and many2many field
- * init: add dataset
- * set_value: compute comands list into ids
+ * For all fields on2many or many2many:
+ * - this.get('value') contains a list of ids and virtual ids
+ * - get_value() return an odoo write command list
*/
var AbstractManyField = common.AbstractField.extend({
init: function(field_manager, node) {
var self = this;
this._super(field_manager, node);
- this.dataset = new One2ManyDataSet(this, this.field.relation);
+ this.dataset = new One2ManyDataSet(this, this.field.relation, this.build_context());
this.dataset.o2m = this;
this.dataset.parent_view = this.view;
this.dataset.child_name = this.name;
+ this.set('value', []);
+ this.starting_ids = [];
+ this.view.on("load_record", this, function () {
+ self.starting_ids = self.get('value');
+ });
this.dataset.on('dataset_changed', this, function() {
- self.dataset_changed();
+ // the editable lists change the dataset without call AbstractManyField methods
+ if (!this.internal_dataset_changed) {
+ this.trigger("change:commands");
+ }
+ });
+ this.on("change:commands", this, function () {
+ this.set({'value': this.dataset.ids.slice()});
});
},
- dataset_changed: function() {
- this.trigger('changed_value');
- },
- /**
- * Set value use command to convert tuple of commands in id list
- */
- set_value: function(value_) {
- this.dataset.reset_ids([]);
- var ids = this.get_ids_from_command(value_);
- this._super(ids);
- this.dataset.reset_ids(ids);
- if (this.dataset.index === null && this.dataset.ids.length > 0) {
- this.dataset.index = 0;
+
+ set_value: function(ids) {
+ ids = (ids || []).slice();
+ if (_.find(ids, function(id) { return typeof(id) === "string"; } )) {
+ throw new Error("set_value of '"+this.name+"' must receive an list of ids without virtual ids.", ids);
+ }
+ if (_.find(ids, function(id) { return typeof(id) !== "number"; } )) {
+ return this.send_commands(ids);
}
- this.dataset_changed();
+ this.dataset.reset_ids(ids);
+ this.set({'value': ids});
},
- // return id for this commands instead of the object ('ALL' to activate all conversion)
- get_ids_from_command_list: ['LINK_TO', 'REPLACE_WITH'],
- get_ids_from_command: function (value_) {
- var self = this;
- var ids;
- var command_list = [];
- if (this.get_ids_from_command_list && this.get_ids_from_command_list !== 'ALL') {
- for (var i=0; i<this.get_ids_from_command_list.length; i++) {
- command_list[i] = commands[this.get_ids_from_command_list[i]];
- }
+ internal_set_value: function(ids) {
+ if (_.isEqual(ids, this.get("value"))) {
+ return;
}
+ var tmp = this.no_rerender;
+ this.no_rerender = true;
+ this.data_replace(ids.slice());
+ this.no_rerender = tmp;
+ },
+
+ /*
+ *@value: data {object} contains all value to send to the db
+ * options {object} options sent to the dataset (like the default values)
+ *@return deferred resolve with the created virtual id
+ */
+ data_create: function (data, options) {
+ return this.send_commands([COMMANDS.create(data)], options);
+ },
+
+ /*
+ *@value: id {int or string} id or virtual id of the record to update
+ * data {object} contains all value to send to the db
+ * options {object} options sent to the dataset
+ *@return deferred
+ */
+ data_update: function (id, data, options) {
+ return this.send_commands([COMMANDS.update(id, data)], options);
+ },
+
+ /*
+ *@value: id {int or string} id or virtual id of the record to add
+ * options {object} options sent to the dataset
+ *@return deferred
+ */
+ data_link: function (id, options) {
+ return this.send_commands([COMMANDS.link_to(id)], options);
+ },
+
+ /*
+ *@value: ids {array} list of ids or virtual ids of the record to add
+ * options {object} options sent to the dataset
+ *@return deferred
+ */
+ data_link_multi: function (ids, options) {
+ return this.send_commands(_.map(ids, function (id) { return COMMANDS.link_to(id); }), options);
+ },
+
+ /*
+ *@value: id {int or string} id or virtual id of the record to unlink or delete (function of field type)
+ *@return deferred
+ */
+ data_delete: function (id) {
+ return this.send_commands([COMMANDS.delete(id)]);
+ },
+
+ /*
+ *@value: ids {array} list of ids or virtual ids of the record who replace the previous list
+ * options {object} options sent to the dataset
+ *@return deferred
+ */
+ data_replace: function (ids, options) {
+ return this.send_commands([COMMANDS.replace_with(ids)], options);
+ },
+
+ /*
+ *@value: ids {array} list of ids or virtual ids of the record to read
+ * fields {array} list of the field to read
+ * options {object} options sent to the dataset
+ *@return deferred resolve with the records
+ */
+ data_read: function (ids, fields, options) {
+ return this.dataset.read_ids(ids, fields, options);
+ },
- value_ = value_ || [];
- if(value_.length >= 1 && value_[0] instanceof Array) {
- ids = [];
- _.each(value_, function(command) {
- var obj = {values: command[2]};
- if (command_list.length && command.indexOf(command_list) === -1) {
- ids.push(obj);
- }
+ /**
+ *Compute the write command list into the dataset
+ *@value: command_list {array} command list
+ * options {object} options for the datasets (eg: the default values)
+ *@return : deferred
+ */
+ send_commands: function (command_list, options) {
+ var self = this;
+ var def = $.Deferred();
+ var mutex = new utils.Mutex();
+ var dataset = this.dataset;
+ var res = true;
+ options = options || {};
+ this.internal_dataset_changed = true;
+
+ _.each(command_list, function(command) {
+ mutex.exec(function() {
switch (command[0]) {
- case commands.CREATE:
- obj.id = _.uniqueId(self.dataset.virtual_id_prefix);
- obj.defaults = {};
- self.dataset.to_create.push(obj);
- self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])}));
- ids.push(obj.id);
- return;
- case commands.UPDATE:
- obj.id = command[1];
- self.dataset.to_write.push(obj);
- self.dataset.cache.push(_.extend(_.clone(obj), {values: _.clone(command[2])}));
- ids.push(obj.id);
- return;
- case commands.DELETE:
- self.dataset.to_delete.push({id: command[1]});
- return;
- case commands.LINK_TO:
- ids.push(command[1]);
- return;
- case commands.DELETE_ALL:
- self.dataset.delete_all = true;
- return;
- case commands.REPLACE_WITH:
- ids = command[2];
+ case COMMANDS.CREATE:
+ var data = _.clone(command[2]);
+ delete data.id;
+ return dataset.create(data, options).then(function (id) {
+ dataset.ids.push(id);
+ res = id;
+ });
+ case COMMANDS.UPDATE:
+ return dataset.write(command[1], command[2], options);
+ case COMMANDS.DELETE:
+ return dataset.unlink(command[1]);
+ case COMMANDS.LINK_TO:
+ if (dataset.ids.indexOf(command[1]) === -1) {
+ return dataset.add_ids([command[1]], options);
+ }
return;
+ case COMMANDS.DELETE_ALL:
+ return dataset.reset_ids([]);
+ case COMMANDS.REPLACE_WITH:
+ dataset.ids = [];
+ return dataset.alter_ids(command[2], options);
+ default:
+ throw new Error("send_commands to '"+self.name+"' receive a non command value.", command_list);
}
});
- return ids;
- } else if (value_.length >= 1 && typeof(value_[0]) === "object") {
- ids = [];
- this.dataset.delete_all = true;
- _.each(value_, function(command) {
- var obj = {values: command};
- obj.id = _.uniqueId(self.dataset.virtual_id_prefix);
- obj.defaults = {};
- self.dataset.to_create.push(obj);
- self.dataset.cache.push(_.clone(obj));
- ids.push(obj.id);
- });
- return ids;
- } else {
- return value_;
+ });
+
+ mutex.exec(function () {
+ def.resolve(res);
+ self.internal_dataset_changed = true;
+ self.trigger("change:commands");
+ });
+ return def;
+ },
+
+ /**
+ *return list of commands: create and update (and delete_all if need) (function of the field type)
+ */
+ get_value: function() {
+ var self = this,
+ is_one2many = this.field.type === "one2many",
+ starting_ids = this.starting_ids.slice(),
+ replace_with_ids = [],
+ add_ids = [],
+ command_list = [],
+ id, index, alter_order;
+
+ _.each(this.get('value'), function (id) {
+ index = starting_ids.indexOf(id);
+ if (index !== -1) {
+ starting_ids.splice(index, 1);
+ }
+ if (alter_order = _.detect(self.dataset.to_create, function(x) {return x.id === id;})) {
+ command_list.push(COMMANDS.create(alter_order.values));
+ return;
+ }
+ if (alter_order = _.detect(self.dataset.to_write, function(x) {return x.id === id;})) {
+ command_list.push(COMMANDS.update(alter_order.id, alter_order.values));
+ return;
+ }
+ if (!is_one2many || self.dataset.delete_all) {
+ replace_with_ids.push(id);
+ } else {
+ command_list.push(COMMANDS.link_to(id));
+ }
+ });
+ if ((!is_one2many || self.dataset.delete_all) && (replace_with_ids.length || starting_ids.length)) {
+ command_list.unshift(COMMANDS.replace_with(replace_with_ids));
}
- }
+
+ _.each(starting_ids, function(id) {
+ if (is_one2many) {
+ command_list.push(COMMANDS.delete(id));
+ } else if (is_one2many && !self.dataset.delete_all) {
+ command_list.push(COMMANDS.unlink(id));
+ }
+ });
+
+ return command_list;
+ },
+
+ is_false: function() {
+ return _(this.get('value')).isEmpty();
+ },
});
@@ -606,10 +725,13 @@ var FieldOne2Many = AbstractManyField.extend({
this.is_loaded = $.Deferred();
this.initial_is_loaded = this.is_loaded;
- this.form_last_update = $.Deferred();
- this.init_form_last_update = this.form_last_update;
this.is_started = false;
this.set_value([]);
+ this.on('change:commands', this, function () {
+ if (this.is_started && !this.no_rerender) {
+ this.reload_current_view();
+ }
+ });
},
start: function() {
this._super.apply(this, arguments);
@@ -665,13 +787,6 @@ var FieldOne2Many = AbstractManyField.extend({
reorderable: false,
});
}
- } else if (view.view_type === "form") {
- if (self.get("effective_readonly")) {
- view.view_type = 'form';
- }
- _.extend(view.options, {
- not_interactible_on_create: true,
- });
} else if (view.view_type === "kanban") {
_.extend(view.options, {
confirm_on_delete: false,
@@ -691,9 +806,6 @@ var FieldOne2Many = AbstractManyField.extend({
this.viewmanager = new One2ManyViewManager(this, this.dataset, views, {});
this.viewmanager.o2m = self;
- var once = $.Deferred().done(function() {
- self.init_form_last_update.resolve();
- });
var def = $.Deferred().done(function() {
self.initial_is_loaded.resolve();
});
@@ -712,14 +824,6 @@ var FieldOne2Many = AbstractManyField.extend({
return true;
});
}
- } else if (view_type === "form") {
- if (self.get("effective_readonly")) {
- $(".oe_form_buttons", controller.$el).children().remove();
- }
- controller.on("load_record", self, function(){
- once.resolve();
- });
- controller.on('pager_action_executed',self,self.save_any_view);
} else if (view_type == "graph") {
self.reload_current_view();
}
@@ -745,15 +849,6 @@ var FieldOne2Many = AbstractManyField.extend({
var view = self.get_active_view();
if (view.type === "list") {
return view.controller.reload_content();
- } else if (view.type === "form") {
- if (self.dataset.index === null && self.dataset.ids.length >= 1) {
- self.dataset.index = 0;
- }
- var act = function() {
- return view.controller.do_show();
- };
- self.form_last_update = self.form_last_update.then(act, act);
- return self.form_last_update;
} else if (view.controller.do_search) {
return view.controller.do_search(self.build_domain(), self.dataset.get_context(), []);
}
@@ -766,35 +861,12 @@ var FieldOne2Many = AbstractManyField.extend({
*/
return (this.viewmanager && this.viewmanager.active_view);
},
- get_ids_from_command_list: 'ALL',
set_value: function(value_) {
this._super(value_);
if (this.is_started && !this.no_rerender) {
- return this.reload_current_view();
- } else {
- return $.when();
+ this.reload_current_view();
}
},
- get_value: function() {
- var self = this;
- if (!this.dataset)
- return [];
- var val = this.dataset.delete_all ? [commands.delete_all()] : [];
- val = val.concat(_.map(this.dataset.ids, function(id) {
- var alter_order = _.detect(self.dataset.to_create, function(x) {return x.id === id;});
- if (alter_order) {
- return commands.create(alter_order.values);
- }
- alter_order = _.detect(self.dataset.to_write, function(x) {return x.id === id;});
- if (alter_order) {
- return commands.update(alter_order.id, alter_order.values);
- }
- return commands.link_to(id);
- }));
- return val.concat(_.map(
- this.dataset.to_delete, function(x) {
- return commands['delete'](x.id);}));
- },
commit_value: function() {
return this.save_any_view();
},
@@ -846,11 +918,6 @@ var One2ManyListView = ListView.extend({
}));
this.on('edit:after', this, this.proxy('_after_edit'));
this.on('save:before cancel:before', this, this.proxy('_before_unedit'));
-
- this.records
- .bind('add', this.proxy("changed_records"))
- .bind('remove', this.proxy("changed_records"));
- this.on('save:after', this, this.proxy("changed_records"));
},
start: function () {
var ret = this._super();
@@ -859,9 +926,6 @@ var One2ManyListView = ListView.extend({
.on('mousedown.handleButtons', 'table button, div a.oe_m2o_cm_button', this.proxy('_button_down'));
return ret;
},
- changed_records: function () {
- this.o2m.dataset_changed();
- },
is_valid: function () {
var self = this;
if (!this.fields_view || !this.editable()){
@@ -906,13 +970,10 @@ var One2ManyListView = ListView.extend({
initial_view: "form",
alternative_form_view: self.o2m.field.views ? self.o2m.field.views.form : undefined,
create_function: function(data, options) {
- return self.o2m.dataset.create(data, options).done(function(r) {
- self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r]));
- self.o2m.dataset.trigger("dataset_changed", r);
- });
+ return self.o2m.data_create(data, options);
},
- read_function: function() {
- return self.o2m.dataset.read_ids.apply(self.o2m.dataset, arguments);
+ read_function: function(ids, fields, options) {
+ return self.o2m.data_read(ids, fields, options);
},
parent_view: self.o2m.view,
child_name: self.o2m.name,
@@ -932,15 +993,15 @@ var One2ManyListView = ListView.extend({
pop.show_element(self.o2m.field.relation, id, self.o2m.build_context(), {
title: _t("Open: ") + self.o2m.string,
write_function: function(id, data) {
- return self.o2m.dataset.write(id, data, {}).done(function() {
+ return self.o2m.data_update(id, data, {}).done(function() {
self.o2m.reload_current_view();
});
},
alternative_form_view: self.o2m.field.views ? self.o2m.field.views.form : undefined,
parent_view: self.o2m.view,
child_name: self.o2m.name,
- read_function: function() {
- return self.o2m.dataset.read_ids.apply(self.o2m.dataset, arguments);
+ read_function: function(ids, fields, options) {
+ return self.o2m.data_read(ids, fields, options);
},
form_view_options: {'not_interactible_on_create':true},
readonly: !this.is_action_enabled('edit') || self.o2m.get("effective_readonly")
@@ -1103,21 +1164,18 @@ var One2ManyViewManager = ViewManager.extend({
pop.show_element(self.o2m.field.relation, id, self.o2m.build_context(), {
title: _t("Open: ") + self.o2m.string,
create_function: function(data, options) {
- return self.o2m.dataset.create(data, options).done(function(r) {
- self.o2m.dataset.set_ids(self.o2m.dataset.ids.concat([r]));
- self.o2m.dataset.trigger("dataset_changed", r);
- });
+ return self.o2m.data_create(data, options);
},
write_function: function(id, data, options) {
- return self.o2m.dataset.write(id, data, {}).done(function() {
+ return self.o2m.data_update(id, data, {}).done(function() {
self.o2m.reload_current_view();
});
},
alternative_form_view: self.o2m.field.views ? self.o2m.field.views.form : undefined,
parent_view: self.o2m.view,
child_name: self.o2m.name,
- read_function: function() {
- return self.o2m.dataset.read_ids.apply(self.o2m.dataset, arguments);
+ read_function: function(ids, fields, options) {
+ return self.o2m.data_read(ids, fields, options);
},
form_view_options: {'not_interactible_on_create':true},
readonly: self.o2m.get("effective_readonly")
@@ -1230,13 +1288,6 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
}
});
},
- is_false: function() {
- return _(this.get("value")).isEmpty();
- },
- get_value: function() {
- var tmp = [commands.replace_with(this.get("value"))];
- return tmp;
- },
get_search_blacklist: function() {
return this.get("value");
},
@@ -1244,9 +1295,7 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
return _.map(data, function(el) {return {name: el[1], id:el[0]};});
},
get_render_data: function(ids){
- var self = this;
- var dataset = new data.DataSetStatic(this, this.field.relation, self.build_context());
- return dataset.name_get(ids);
+ return this.dataset.name_get(ids);
},
render_tag: function(data) {
var self = this;
@@ -1260,7 +1309,6 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
},
render_value: function() {
var self = this;
- var dataset = new data.DataSetStatic(this, this.field.relation, self.build_context());
var values = self.get("value");
var handle_names = function(data) {
if (self.isDestroyed())
@@ -1291,7 +1339,7 @@ var FieldMany2ManyTags = AbstractManyField.extend(common.CompletionFieldMixin, c
width: width,
minHeight: height
});
- },
+ },
_search_create_popup: function() {
this.ignore_blur = true;
return common.CompletionFieldMixin._search_create_popup.apply(this, arguments);
@@ -1350,22 +1398,13 @@ var FieldMany2Many = AbstractManyField.extend(common.ReinitializeFieldMixin, {
this.list_view.destroy();
this.list_view = undefined;
},
- get_value: function() {
- return [commands.replace_with(this.get('value'))];
- },
- is_false: function () {
- return _(this.get("value")).isEmpty();
- },
render_value: function() {
var self = this;
- this.dataset.set_ids(this.get("value"));
+ //this.dataset.set_ids(this.get('value') || []);
this.render_value_dm.add(this.is_loaded).then(function() {
return self.list_view.reload_content();
});
- },
- dataset_changed: function() {
- this.internal_set_value(this.dataset.ids);
- },
+ }
});
var Many2ManyDataSet = data.DataSetStatic.extend({
@@ -1399,17 +1438,7 @@ var Many2ManyListView = ListView.extend(/** @lends instance.web.form.Many2ManyLi
);
var self = this;
pop.on("elements_selected", self, function(element_ids) {
- var reload = false;
- _(element_ids).each(function (id) {
- if(! _.detect(self.dataset.ids, function(x) {return x == id;})) {
- self.dataset.set_ids(self.dataset.ids.concat([id]));
- self.m2m_field.dataset_changed();
- reload = true;
- }
- });
- if (reload) {
- self.reload_content();
- }
+ return self.o2m.data_link_multi(element_ids);
});
},
do_activate_record: function(index, id) {
@@ -1420,7 +1449,10 @@ var Many2ManyListView = ListView.extend(/** @lends instance.web.form.Many2ManyLi
alternative_form_view: this.m2m_field.field.views ? this.m2m_field.field.views.form : undefined,
readonly: this.getParent().get("effective_readonly")
});
- pop.on('write_completed', self, self.reload_content);
+ pop.on('write_completed', self, function () {
+ self.dataset.evict_record(id);
+ self.reload_content();
+ });
},
do_button_action: function(name, id, callback) {
var self = this;
@@ -1467,9 +1499,6 @@ var FieldMany2ManyKanban = AbstractManyField.extend(common.CompletionFieldMixin,
});
});
},
- get_value: function() {
- return [commands.replace_with(this.get('value'))];
- },
load_view: function() {
var self = this;
var Many2ManyKanbanView = core.view_registry.get('many2many_kanban');
@@ -1503,9 +1532,6 @@ var FieldMany2ManyKanban = AbstractManyField.extend(common.CompletionFieldMixin,
return self.kanban_view.do_search(self.build_domain(), self.dataset.get_context(), []);
});
},
- dataset_changed: function() {
- this.set({'value': this.dataset.ids});
- },
open_popup: function(type, unused) {
if (type !== "form")
return;
@@ -1522,13 +1548,7 @@ var FieldMany2ManyKanban = AbstractManyField.extend(common.CompletionFieldMixin,
this.build_context()
);
pop.on("elements_selected", self, function(element_ids) {
- _.each(element_ids, function(one_id) {
- if(! _.detect(self.dataset.ids, function(x) {return x == one_id;})) {
- self.dataset.set_ids([].concat(self.dataset.ids, [one_id]));
- self.dataset_changed();
- self.render_value();
- }
- });
+ return self.data_link_multi(element_ids);
});
} else {
var id = self.dataset.ids[self.dataset.index];
@@ -1536,7 +1556,7 @@ var FieldMany2ManyKanban = AbstractManyField.extend(common.CompletionFieldMixin,
pop.show_element(self.field.relation, id, self.build_context(), {
title: _t("Open: ") + self.string,
write_function: function(id, data, options) {
- return self.dataset.write(id, data, {}).done(function() {
+ return self.data_update(id, data, {}).done(function() {
self.render_value();
});
},
@@ -1577,9 +1597,6 @@ var FieldMany2ManyBinaryMultiFiles = AbstractManyField.extend(common.Reinitializ
initialize_content: function() {
this.$el.on('change', 'input.oe_form_binary_file', this.on_file_change );
},
- get_value: function() {
- return [commands.replace_with(this.get("value"))];
- },
get_file_url: function (attachment) {
return this.session.url('/web/binary/saveas', {model: 'ir.attachment', field: 'datas', filename_field: 'datas_fname', id: attachment.id});
},
@@ -1709,7 +1726,6 @@ var FieldMany2ManyCheckBoxes = AbstractManyField.extend(common.ReinitializeField
className: "oe_form_many2many_checkboxes",
init: function() {
this._super.apply(this, arguments);
- this.set("value", {});
this.set("records", []);
this.field_manager.on("view_content_has_changed", this, function() {
var domain = new data.CompoundDomain(this.build_domain()).eval();
@@ -1735,38 +1751,18 @@ var FieldMany2ManyCheckBoxes = AbstractManyField.extend(common.ReinitializeField
});
},
render_value: function() {
- this.$().html(QWeb.render("FieldMany2ManyCheckBoxes", {widget: this, selected: this.get("value")}));
+ this.$().html(QWeb.render("FieldMany2ManyCheckBoxes", {widget: this}));
var inputs = this.$("input");
inputs.change(_.bind(this.from_dom, this));
if (this.get("effective_readonly"))
inputs.attr("disabled", "true");
},
from_dom: function() {
- var new_value = {};
- this.$("input").each(function() {
- var elem = $(this);
- new_value[elem.data("record-id")] = elem.is(":checked") ? true : undefined;
- });
- if (! _.isEqual(new_value, this.get("value")))
+ var new_value = this.$("input:checked").map(function() { return +$(this).data("record-id"); }).get();
+ if (! _.isEqual(new_value, this.get("value"))) {
this.internal_set_value(new_value);
- },
- set_value: function(value_) {
- var value_ = this.get_ids_from_command(value_);
- var formatted = {};
- _.each(value_, function(el) {
- formatted[JSON.stringify(el)] = true;
- });
- this.set({'value': formatted});
- },
- get_value: function() {
- var value = _.filter(_.keys(this.get("value")), function(el) {
- return this.get("value")[el];
- }, this);
- value = _.map(value, function(el) {
- return JSON.parse(el);
- });
- return [commands.replace_with(value)];
- },
+ }
+ }
});
@@ -1778,7 +1774,7 @@ core.form_widget_registry
.add('one2many', FieldOne2Many)
.add('one2many_list', FieldOne2Many)
.add('many2many_binary', FieldMany2ManyBinaryMultiFiles)
- .add('many2many_checkboxes', FieldMany2ManyCheckBoxes)
+ .add('many2many_checkboxes', FieldMany2ManyCheckBoxes);
return {
FieldMany2ManyTags: FieldMany2ManyTags,
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 285c9066c66..9d9b54e4d74 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -1932,10 +1932,10 @@
<t t-name="FieldMany2ManyCheckBoxes">
<t t-foreach="widget.get('records')" t-as="record">
<div>
- <t t-if="selected[record[0]]">
+ <t t-if="widget.get('value').indexOf(record[0]) !== -1">
<input type="checkbox" t-att-data-record-id="JSON.stringify(record[0])" checked="true"/>
</t>
- <t t-if="! selected[record[0]]">
+ <t t-if="widget.get('value').indexOf(record[0]) === -1">
<input type="checkbox" t-att-data-record-id="JSON.stringify(record[0])"/>
</t>
<t t-esc="record[1]"/>