diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js index b35c42810a8..aa59598e712 100644 --- a/addons/web/static/src/js/views/list/list_renderer.js +++ b/addons/web/static/src/js/views/list/list_renderer.js @@ -66,7 +66,7 @@ var ListRenderer = BasicRenderer.extend({ init: function (parent, state, params) { this._super.apply(this, arguments); this._preprocessColumns(); - this.columnInvisibleFields = params.columnInvisibleFields; + this.columnInvisibleFields = params.columnInvisibleFields || {}; this.rowDecorations = this._extractDecorationAttrs(this.arch); this.fieldDecorations = {}; for (const field of this.arch.children.filter(c => c.tag === 'field')) { @@ -86,7 +86,7 @@ var ListRenderer = BasicRenderer.extend({ * @override */ willStart: function () { - this._processColumns(this.columnInvisibleFields || {}); + this._processColumns(this.columnInvisibleFields); return this._super.apply(this, arguments); }, @@ -108,7 +108,8 @@ var ListRenderer = BasicRenderer.extend({ updateState: function (state, params) { this._setState(state); this.isGrouped = this.state.groupedBy.length > 0; - this._processColumns(params.columnInvisibleFields || {}); + this.columnInvisibleFields = params.columnInvisibleFields || {}; + this._processColumns(this.columnInvisibleFields); if (params.selectedRecords) { this.selection = params.selectedRecords; } @@ -369,7 +370,11 @@ var ListRenderer = BasicRenderer.extend({ var reject = c.attrs.modifiers.column_invisible; // If there is an evaluated domain for the field we override the node // attribute to have the evaluated modifier value. - if (c.attrs.name in columnInvisibleFields) { + if (c.tag === "button_group") { + // FIXME: 'column_invisible' attribute is available for fields *and* buttons, + // so 'columnInvisibleFields' variable name is misleading, it should be renamed + reject = c.children.every(child => columnInvisibleFields[child.attrs.name]); + } else if (c.attrs.name in columnInvisibleFields) { reject = columnInvisibleFields[c.attrs.name]; } if (!reject && c.attrs.widget === 'handle') { @@ -523,7 +528,9 @@ var ListRenderer = BasicRenderer.extend({ if (node.tag === 'button_group') { for (const buttonNode of node.children) { - $td.append(this._renderButton(record, buttonNode)); + if (!this.columnInvisibleFields[buttonNode.attrs.name]) { + $td.append(this._renderButton(record, buttonNode)); + } } return $td; } else if (node.tag === 'widget') { @@ -1237,7 +1244,7 @@ var ListRenderer = BasicRenderer.extend({ keyParts: this._getOptionalColumnsStorageKeyParts(), optionalColumnsEnabled: this.optionalColumnsEnabled, }); - this._processColumns(this.columnInvisibleFields || {}); + this._processColumns(this.columnInvisibleFields); this._render().then(function () { self._onToggleOptionalColumnDropdown(ev); }); diff --git a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js index f3e5b036fb5..a7f351c4e76 100644 --- a/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js +++ b/addons/web/static/tests/fields/relational_fields/field_one2many_tests.js @@ -8444,6 +8444,94 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('column_invisible attrs on a button in a one2many list', async function (assert) { + assert.expect(6); + + this.data.partner.records[0].p = [2]; + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` +
`, + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + assert.strictEqual(form.$('.o_field_widget[name=product_id] input').val(), ''); + assert.containsN(form, '.o_list_table th', 2); // foo + trash bin + assert.containsNone(form, '.some_button'); + + await testUtils.fields.many2one.clickOpenDropdown('product_id'); + await testUtils.fields.many2one.clickHighlightedItem('product_id'); + + assert.strictEqual(form.$('.o_field_widget[name=product_id] input').val(), 'xphone'); + assert.containsN(form, '.o_list_table th', 3); // foo + button + trash bin + assert.containsOnce(form, '.some_button'); + + form.destroy(); + }); + + QUnit.test('column_invisible attrs on adjacent buttons', async function (assert) { + assert.expect(14); + + this.data.partner.records[0].p = [2]; + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` + `, + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + assert.strictEqual(form.$('.o_field_widget[name=product_id] input').val(), ''); + assert.strictEqual(form.$('.o_field_widget[name=trululu] input').val(), 'aaa'); + assert.containsN(form, '.o_list_table th', 4); // button group 1 + foo + button group 2 + trash bin + assert.containsOnce(form, '.some_button1'); + assert.containsOnce(form, '.some_button2'); + assert.containsOnce(form, '.some_button3'); + assert.containsNone(form, '.some_button4'); + + await testUtils.fields.many2one.clickOpenDropdown('product_id'); + await testUtils.fields.many2one.clickHighlightedItem('product_id'); + + assert.strictEqual(form.$('.o_field_widget[name=product_id] input').val(), 'xphone'); + assert.strictEqual(form.$('.o_field_widget[name=trululu] input').val(), 'aaa'); + assert.containsN(form, '.o_list_table th', 3); // button group 1 + foo + trash bin + assert.containsOnce(form, '.some_button1'); + assert.containsNone(form, '.some_button2'); + assert.containsNone(form, '.some_button3'); + assert.containsNone(form, '.some_button4'); + + form.destroy(); + }); + QUnit.test('one2many column visiblity depends on onchange of parent field', async function (assert) { assert.expect(3);