From 015ad5ff7398326a51fb0aa08a0ffdfe78af01f1 Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Fri, 5 Mar 2021 08:25:52 +0000 Subject: [PATCH] [FIX] web: can edit many2many_checkboxes with 40+ values Before this commit, if the widget "many2many_checkboxes" was set on a field with more than 40 values in the comodel (i.e. more than 40 checkboxes displayed), (un)selecting a checkbox that wasn't in the first 40 checkboxes crashed. This was due to the default x2many limit of 40: we only created a datapoint for the first 40 values, whereas we could have up to 100 values to process (name_search server-side limit). Note that this limit of 40 had no other impact than limitating the number of records processed by the BasicModel, the maximum number of checkboxes displayed being ruled by the name_search server-side limit. This commit ensures that all values returned by the server (at most 100 when this message is written) are processed and can be edited as expected. opw~2439041 X-original-commit: d037d12753179d890459b23319b0d769fce62771 --- .../static/src/js/fields/relational_fields.js | 3 ++ .../tests/fields/relational_fields_tests.js | 50 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 39c66abbfab..5a9b847bb8e 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -2826,6 +2826,9 @@ var FieldMany2ManyCheckBoxes = AbstractField.extend({ specialData: "_fetchSpecialRelation", supportedFieldTypes: ['many2many'], isQuickEditable: true, + // set an arbitrary high limit to ensure that all data returned by the server + // are processed by the BasicModel (otherwise it would be 40) + limit: 100000, init: function () { this._super.apply(this, arguments); this.m2mValues = this.record.specialData[this.name]; diff --git a/addons/web/static/tests/fields/relational_fields_tests.js b/addons/web/static/tests/fields/relational_fields_tests.js index e0327cfeb6d..880a6e95409 100644 --- a/addons/web/static/tests/fields/relational_fields_tests.js +++ b/addons/web/static/tests/fields/relational_fields_tests.js @@ -2534,6 +2534,56 @@ QUnit.module('relational_fields', { form.destroy(); }); + QUnit.test('widget many2many_checkboxes with 40+ values', async function (assert) { + // 40 is the default limit for x2many fields. However, the many2many_checkboxes is a + // special field that fetches its data through the fetchSpecialData mechanism, and it + // uses the name_search server-side limit of 100. This test comes with a fix for a bug + // that occurred when the user (un)selected a checkbox that wasn't in the 40 first checkboxes, + // because the piece of data corresponding to that checkbox hadn't been processed by the + // BasicModel, whereas the code handling the change assumed it had. + assert.expect(3); + + const records = []; + for (let id = 1; id <= 90; id++) { + records.push({ + id, + display_name: `type ${id}`, + color: id % 7, + }); + } + this.data.partner_type.records = records; + this.data.partner.records[0].timmy = records.map((r) => r.id); + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
', + res_id: 1, + async mockRPC(route, args) { + if (args.method === 'write') { + const expectedIds = records.map((r) => r.id); + expectedIds.pop(); + assert.deepEqual(args.args[1].timmy, [[6, false, expectedIds]]); + } + return this._super(...arguments); + }, + viewOptions: { + mode: 'edit', + }, + }); + + assert.containsN(form, '.o_field_widget[name=timmy] input[type=checkbox]:checked', 90); + + // toggle the last value + await testUtils.dom.click(form.$('.o_field_widget[name=timmy] input[type=checkbox]:last')); + assert.notOk(form.$('.o_field_widget[name=timmy] input[type=checkbox]:last').is(':checked')); + + await testUtils.form.clickSave(form); + + form.destroy(); + }); + QUnit.module('FieldMany2ManyBinaryMultiFiles'); QUnit.test('widget many2many_binary', async function (assert) {