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 6f21653b70c..2e2b5856ecd 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 @@ -1005,6 +1005,17 @@ ListRenderer.include({ } return $body; }, + /** + * @override + * @private + */ + _renderFooter: function () { + const $footer = this._super.apply(this, arguments); + if (this.addTrashIcon) { + $footer.find('tr').append($('')); + } + return $footer; + }, /** * Override to optionally add a th in the header for the remove icon column. * 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 5daa33125a7..468ac4d15c1 100644 --- a/addons/web/static/src/js/views/list/list_renderer.js +++ b/addons/web/static/src/js/views/list/list_renderer.js @@ -287,7 +287,14 @@ var ListRenderer = BasicRenderer.extend({ if (c.attrs.name in columnInvisibleFields) { reject = columnInvisibleFields[c.attrs.name]; } - + if (c.attrs.class) { + if (c.attrs.class.match(/\boe_edit_only\b/)) { + c.attrs.editOnly = true; + } + if (c.attrs.class.match(/\boe_read_only\b/)) { + c.attrs.readOnly = true; + } + } if (!reject && c.attrs.widget === 'handle') { self.handleField = c.attrs.name; if (self.isGrouped) { @@ -331,6 +338,12 @@ var ListRenderer = BasicRenderer.extend({ if (config.isDebug()) { $cell.addClass(column.attrs.name); } + if (column.attrs.editOnly) { + $cell.addClass('oe_edit_only'); + } + if (column.attrs.readOnly) { + $cell.addClass('oe_read_only'); + } if (column.attrs.name in aggregateValues) { var field = self.state.fields[column.attrs.name]; var value = aggregateValues[column.attrs.name].value; @@ -394,6 +407,12 @@ var ListRenderer = BasicRenderer.extend({ tdClassName += (' o_' + node.attrs.widget + '_cell'); } } + if (node.attrs.editOnly) { + tdClassName += ' oe_edit_only'; + } + if (node.attrs.readOnly) { + tdClassName += ' oe_read_only'; + } var $td = $('', { class: tdClassName, tabindex: -1 }); // We register modifiers on the element so that it gets the correct @@ -748,13 +767,11 @@ var ListRenderer = BasicRenderer.extend({ if (name) { $th.attr('data-name', name); } - if (node.attrs.class) { - if (node.attrs.class.indexOf('oe_edit_only') !== -1) { - $th.addClass('oe_edit_only'); - } - if (node.attrs.class.indexOf('oe_read_only') !== -1) { - $th.addClass('oe_read_only'); - } + if (node.attrs.editOnly) { + $th.addClass('oe_edit_only'); + } + if (node.attrs.readOnly) { + $th.addClass('oe_read_only'); } if (!field) { return $th; 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 35b4be9f25e..60f3398c88c 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 @@ -8705,6 +8705,42 @@ QUnit.module('fields', {}, function () { form.destroy(); }); + + QUnit.test('editable one2many list with oe_read_only button', async function (assert) { + assert.expect(9); + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: `
+ + + +