diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index eefb771c69a..c539a3ce12d 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -1071,6 +1071,7 @@ var FieldX2Many = AbstractField.extend({ this.currentColInvisibleFields = this._evalColumnInvisibleFields(); return this.renderer.updateState(this.value, { columnInvisibleFields: this.currentColInvisibleFields, + keepWidths: true, }).then(function () { self.pager.updateState({ size: self.value.count }); }); diff --git a/addons/web/static/src/js/views/list/list_controller.js b/addons/web/static/src/js/views/list/list_controller.js index c09abc54b91..1e109d7c0b8 100644 --- a/addons/web/static/src/js/views/list/list_controller.js +++ b/addons/web/static/src/js/views/list/list_controller.js @@ -247,7 +247,7 @@ var ListController = BasicController.extend({ }); }).then(function (recordID) { var state = self.model.get(self.handle); - self.renderer.updateState(state, {}) + self.renderer.updateState(state, {keepWidths: true}) .then(function () { self.renderer.editRecord(recordID); }).then(self._updatePager.bind(self)); @@ -405,7 +405,7 @@ var ListController = BasicController.extend({ .then(() => { this._updateButtons('readonly'); const state = this.model.get(this.handle); - this.renderer.updateState(state, {}); + this.renderer.updateState(state, {keepWidths: true}); resolve(Object.keys(changes)); }) .guardedCatch(rejectAndDiscard); 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 a1b23317bf1..b3ee0e43fa4 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 @@ -44,6 +44,7 @@ ListRenderer.include({ this._super.apply(this, arguments); this.editable = params.editable; + this.columnWidths = false; // if addCreateLine (resp. addCreateLineInGroups) is true, the renderer // will add a 'Add a line' link at the bottom of the list view (resp. @@ -491,6 +492,13 @@ 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) { + return $(th).outerWidth(); + }); + } if (params.noRender) { // the state changed, but we won't do a re-rendering right now, so // remove computed modifiers data (as they are obsolete) to force @@ -537,10 +545,21 @@ ListRenderer.include({ // there is no record -> 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(function () { - var $th = $(this); - $th.css('width', $th.outerWidth() + 'px'); + $thead.find('th').each((index, th) => { + var $th = $(th); + $th.css('width', restoreWidths ? this.columnWidths[index] : $th.outerWidth() + 'px'); }); this.$('table').css('table-layout', 'fixed'); }, 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 f4752bc9751..e8d8785b77a 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 @@ -8541,6 +8541,71 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + QUnit.test('column widths are kept when adding first record in o2m', async function (assert) { + assert.expect(2); + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + }); + + var width = form.$('th[data-name="date"]')[0].offsetWidth; + + await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a')); + + assert.containsOnce(form, '.o_data_row'); + assert.strictEqual(form.$('th[data-name="date"]')[0].offsetWidth, width); + + form.destroy(); + }); + + QUnit.test('column widths are kept when editing a record in o2m', async function (assert) { + assert.expect(2); + + this.data.partner.records[0].p = [2]; + + var form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + viewOptions: { + mode: 'edit', + }, + }); + + var width = form.$('th[data-name="date"]')[0].offsetWidth; + + await testUtils.dom.click(form.$('.o_data_row .o_data_cell:first')); + + assert.strictEqual(form.$('th[data-name="date"]')[0].offsetWidth, width); + + var longVal = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed blandit, ' + + 'justo nec tincidunt feugiat, mi justo suscipit libero, sit amet tempus ipsum ' + + 'purus bibendum est.'; + await testUtils.fields.editInput(form.$('.o_field_widget[name=foo]'), longVal); + + assert.strictEqual(form.$('th[data-name="date"]')[0].offsetWidth, width); + + form.destroy(); + }); }); }); }); diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index 7915ab2964c..c761993b674 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -1517,6 +1517,94 @@ QUnit.module('Views', { list.destroy(); }); + QUnit.test('column widths are kept when adding first record', async function (assert) { + assert.expect(2); + + this.data.foo.records = []; // in this scenario, we start with no records + var list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '' + + '' + + '' + + '', + }); + + var width = list.$('th[data-name="datetime"]')[0].offsetWidth; + + await testUtils.dom.click(list.$buttons.find('.o_list_button_add')); + + assert.containsOnce(list, '.o_data_row'); + assert.strictEqual(list.$('th[data-name="datetime"]')[0].offsetWidth, width); + + list.destroy(); + }); + + QUnit.test('column widths are kept when editing a record', async function (assert) { + assert.expect(3); + + var list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '' + + '' + + '' + + '', + }); + + var width = list.$('th[data-name="datetime"]')[0].offsetWidth; + + await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_data_cell:eq(1)')); + assert.containsOnce(list, '.o_selected_row'); + + var longVal = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed blandit, ' + + 'justo nec tincidunt feugiat, mi justo suscipit libero, sit amet tempus ipsum purus ' + + 'bibendum est.'; + await testUtils.fields.editInput(list.$('.o_field_widget[name=text]'), longVal); + await testUtils.dom.click(list.$buttons.find('.o_list_button_save')); + + assert.containsNone(list, '.o_selected_row'); + assert.strictEqual(list.$('th[data-name="datetime"]')[0].offsetWidth, width); + + list.destroy(); + }); + + QUnit.test('column widths are kept when editing multiple records', async function (assert) { + assert.expect(4); + + var list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '' + + '' + + '' + + '', + }); + + var width = list.$('th[data-name="datetime"]')[0].offsetWidth; + + // select two records and edit + await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_list_record_selector input')); + await testUtils.dom.click(list.$('.o_data_row:eq(1) .o_list_record_selector input')); + await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_data_cell:eq(1)')); + + assert.containsOnce(list, '.o_selected_row'); + var longVal = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed blandit, ' + + 'justo nec tincidunt feugiat, mi justo suscipit libero, sit amet tempus ipsum purus ' + + 'bibendum est.'; + await testUtils.fields.editInput(list.$('.o_field_widget[name=text]'), longVal); + assert.containsOnce(document.body, '.modal'); + await testUtils.dom.click($('.modal .btn-primary')); + + assert.containsNone(list, '.o_selected_row'); + assert.strictEqual(list.$('th[data-name="datetime"]')[0].offsetWidth, width); + + list.destroy(); + }); + QUnit.test('row height should not change when switching mode', async function (assert) { // Warning: this test is css dependant assert.expect(3);