diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js index 73f59e5d13c..a11b326991b 100644 --- a/addons/web/static/src/js/views/list/list_editable_renderer.js +++ b/addons/web/static/src/js/views/list/list_editable_renderer.js @@ -492,7 +492,6 @@ ListRenderer.include({ * @override */ updateState: function (state, params) { - this.oldColumns = this.columns; this.columnWidths = false; if (params.keepWidths) { this.columnWidths = this.$('thead th').toArray().map(function (th) { @@ -542,24 +541,14 @@ ListRenderer.include({ */ _freezeColumnWidths: function () { if (!this._hasVisibleRecords(this.state) && !this.columnWidths) { - // there is no record -> don't force column's widths w.r.t. their label + // there is no record nor widths to restore -> don't force column's + // widths w.r.t. their label return; } - let restoreWidths = false; - if (this.columnWidths) { - if (this.oldColumns && this.oldColumns.length === this.columns.length) { - for (let i = 0; i < this.oldColumns.length; i++) { - if (this.oldColumns[i] !== this.columns[i]) { - break; - } - restoreWidths = (i === this.oldColumns.length - 1); // columns are as before - } - } - } var $thead = this.$('thead'); $thead.find('th').each((index, th) => { var $th = $(th); - $th.css('width', restoreWidths ? this.columnWidths[index] : $th.outerWidth() + 'px'); + $th.css('width', this.columnWidths ? this.columnWidths[index] : $th.outerWidth() + 'px'); }); this.$('table').css('table-layout', 'fixed'); }, @@ -841,22 +830,37 @@ ListRenderer.include({ }); }, /** - * Overridden to set weights or explicit width on columns for the fixed layout. + * Override to compute the (relative or absolute) width of each column. * * @override * @private */ _processColumns: function () { + const oldColumns = this.columns; this._super.apply(this, arguments); if (this.editable) { - this.columns.forEach((column) => { - const width = this._getColumnWidth(column); - if (width.match(/[a-zA-Z]/)) { // absolute width with measure unit (e.g. 100px) - column.attrs.absoluteWidth = width; - } else { // relative width expressed as a weight (e.g. 1.5) - column.attrs.relativeWidth = parseFloat(width, 10); + // check if stored widths still apply + if (this.columnWidths && oldColumns && oldColumns.length === this.columns.length) { + for (let i = 0; i < oldColumns.length; i++) { + if (oldColumns[i] !== this.columns[i]) { + this.columnWidths = false; // columns changed, so forget stored widths + break; + } } - }); + } else { + this.columnWidths = false; // columns changed, so forget stored widths + } + // if we don't have widths yet, computed them + if (!this.columnWidths) { + this.columns.forEach((column) => { + const width = this._getColumnWidth(column); + if (width.match(/[a-zA-Z]/)) { // absolute width with measure unit (e.g. 100px) + column.attrs.absoluteWidth = width; + } else { // relative width expressed as a weight (e.g. 1.5) + column.attrs.relativeWidth = parseFloat(width, 10); + } + }); + } } }, /** 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 19883a53c73..eb4cd9986cc 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 @@ -2,10 +2,12 @@ odoo.define('web.field_one_to_many_tests', function (require) { "use strict"; var AbstractField = require('web.AbstractField'); +var AbstractStorageService = require('web.AbstractStorageService'); var FormView = require('web.FormView'); var KanbanRecord = require('web.KanbanRecord'); var ListRenderer = require('web.ListRenderer'); var NotificationService = require('web.NotificationService'); +var RamStorage = require('web.RamStorage'); var relationalFields = require('web.relational_fields'); var testUtils = require('web.test_utils'); var fieldUtils = require('web.field_utils'); @@ -8638,6 +8640,51 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + + QUnit.test('column widths are correct after toggling optional fields', async function (assert) { + assert.expect(2); + + var RamStorageService = AbstractStorageService.extend({ + storage: new RamStorage(), + }); + + this.data.partner.records[0].p = [2]; + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + // we want the list to remain empty + '' + + '' + + '' + + '' + + '
', + services: { + local_storage: RamStorageService, + }, + }); + + // date fields have an hardcoded width, which apply when there is no + // record, and should be kept afterwards + let width = form.$('th[data-name="date"]')[0].offsetWidth; + + // create a record to store the current widths, but discard it directly to keep + // the list empty (otherwise, the browser automatically computes the optimal widths) + await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a')); + + assert.strictEqual(form.$('th[data-name="date"]')[0].offsetWidth, width); + + await testUtils.dom.click(form.$('.o_optional_columns_dropdown_toggle')); + await testUtils.dom.click(form.$('div.o_optional_columns div.dropdown-item input')); + + assert.strictEqual(form.$('th[data-name="date"]')[0].offsetWidth, width); + + form.destroy(); + }); }); }); });