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 fc026a332f0..42b31bc2e3c 100644 --- a/addons/web/static/src/js/views/list/list_renderer.js +++ b/addons/web/static/src/js/views/list/list_renderer.js @@ -848,8 +848,8 @@ var ListRenderer = BasicRenderer.extend({ }, /** * Render a single with the informations for a column. If it is not a - * field, the th will be empty. Otherwise, it will contains all relevant - * information for the field. + * field or nolabel attribute is set to "1", the th will be empty. + * Otherwise, it will contains all relevant information for the field. * * @private * @param {Object} node @@ -874,7 +874,7 @@ var ListRenderer = BasicRenderer.extend({ if (node.attrs.readOnly) { $th.addClass('oe_read_only'); } - if (!field) { + if (!field || node.attrs.nolabel === '1') { return $th; } var description = string || field.string; diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index 98b85b2270e..a0c7d4d00ce 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -559,6 +559,19 @@ QUnit.module('Views', { list.destroy(); }); + QUnit.test('field with nolabel has no title', async function (assert) { + assert.expect(1); + + const list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + }); + assert.strictEqual(list.$('thead tr:first th:eq(1)').text(), ""); + list.destroy(); + }); + QUnit.test('field titles are not escaped', async function (assert) { assert.expect(2); @@ -3207,6 +3220,39 @@ QUnit.module('Views', { list.destroy(); }); + QUnit.test('do not sort records when clicking on header with nolabel', async function (assert) { + assert.expect(6); + + this.data.foo.fields.foo.sortable = true; + + let nbSearchRead = 0; + const list = await createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + mockRPC: function (route) { + if (route === '/web/dataset/search_read') { + nbSearchRead++; + } + return this._super.apply(this, arguments); + }, + }); + + assert.strictEqual(nbSearchRead, 1, "should have done one search_read"); + assert.strictEqual(list.$('.o_data_cell').text(), "yop10blip9gnap17blip-4"); + + await testUtils.dom.click(list.$('thead th[data-name="int_field"]')); + assert.strictEqual(nbSearchRead, 2, "should have done one other search_read"); + assert.strictEqual(list.$('.o_data_cell').text(), "blip-4blip9yop10gnap17"); + + await testUtils.dom.click(list.$('thead th[data-name="foo"]')); + assert.strictEqual(nbSearchRead, 2, "shouldn't have done anymore search_read"); + assert.strictEqual(list.$('.o_data_cell').text(), "blip-4blip9yop10gnap17"); + + list.destroy(); + }); + QUnit.test('use default_order', async function (assert) { assert.expect(3); diff --git a/doc/reference/views.rst b/doc/reference/views.rst index d3c9b7fb60c..a0e4011e1d6 100644 --- a/doc/reference/views.rst +++ b/doc/reference/views.rst @@ -1480,6 +1480,9 @@ Possible children elements of the list view are: ``{$name}`` can be ``bf`` (``font-weight: bold``), ``it`` (``font-style: italic``), or any `bootstrap contextual color`_ (``danger``, ``info``, ``muted``, ``primary``, ``success`` or ``warning``). + ``nolabel`` + if set to "1", the column header will remain empty. Also, the column + won't be sortable. .. note::