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: ``,
+ res_id: 1,
+ });
+
+ assert.containsN(form, '.o_list_view thead th:visible', 2);
+ assert.containsN(form, '.o_list_view tbody .o_data_row td:visible', 2);
+ assert.containsN(form, '.o_list_view tfoot td:visible', 2);
+ assert.containsNone(form, '.o_list_record_remove_header');
+
+ await testUtils.form.clickEdit(form);
+
+ // should have two visible columns in edit: foo + trash
+ assert.hasClass(form.$('.o_form_view'), 'o_form_editable');
+ assert.containsN(form, '.o_list_view thead th:visible', 2);
+ assert.containsN(form, '.o_list_view tbody .o_data_row td:visible', 2);
+ assert.containsN(form, '.o_list_view tfoot td:visible', 2);
+ assert.containsOnce(form, '.o_list_record_remove_header');
+
+ form.destroy();
+ });
+
});
});
});
|