diff --git a/addons/web/static/src/views/list/list_renderer.js b/addons/web/static/src/views/list/list_renderer.js
index 555e8618e2c..f5531e2fc71 100644
--- a/addons/web/static/src/views/list/list_renderer.js
+++ b/addons/web/static/src/views/list/list_renderer.js
@@ -76,6 +76,18 @@ export class ListRenderer extends Component {
this.longTouchTimer = null;
this.touchStartMs = 0;
+ /**
+ * When resizing, it's possible that the pointer is not above the resize
+ * handle (by some few pixel difference). During this scenario, click event
+ * will be triggered on the column title which will reorder the column.
+ * Column resize that triggers a reorder is not a good UX and we prevent this
+ * using the following state variables: `resizing` and `preventReorder` which
+ * are set during the column's click (onClickSortColumn), mouseup
+ * (onColumnTitleMouseUp) and onStartResize events.
+ */
+ this.resizing = false;
+ this.preventReorder = false;
+
this.creates = this.props.archInfo.creates.length
? this.props.archInfo.creates
: [{ type: "create", string: this.env._t("Add a line") }];
@@ -863,6 +875,10 @@ export class ListRenderer extends Component {
}
onClickSortColumn(column) {
+ if (this.preventReorder) {
+ this.preventReorder = false;
+ return;
+ }
if (this.props.list.editedRecord || this.props.list.model.useSampleModel) {
return;
}
@@ -870,6 +886,8 @@ export class ListRenderer extends Component {
const list = this.props.list;
if (this.isSortable(column)) {
list.sortBy(fieldName);
+ // don't resize column when reordering.
+ this.keepColumnWidths = true;
}
}
@@ -1684,6 +1702,12 @@ export class ListRenderer extends Component {
}
}
+ onColumnTitleMouseUp() {
+ if (this.resizing) {
+ this.preventReorder = true;
+ }
+ }
+
/**
* Handles the resize feature on the column headers
*
@@ -1691,6 +1715,7 @@ export class ListRenderer extends Component {
* @param {MouseEvent} ev
*/
onStartResize(ev) {
+ this.resizing = true;
const table = this.tableRef.el;
const th = ev.target.closest("th");
const handler = th.querySelector(".o_resize");
@@ -1733,6 +1758,7 @@ export class ListRenderer extends Component {
// Mouse or keyboard events : stop resize
const stopResize = (ev) => {
+ this.resizing = false;
// Ignores the 'left mouse button down' event as it used to start resizing
if (ev.type === "mousedown" && ev.which === 1) {
return;
diff --git a/addons/web/static/src/views/list/list_renderer.xml b/addons/web/static/src/views/list/list_renderer.xml
index d843463bb86..299cdedf7d2 100644
--- a/addons/web/static/src/views/list/list_renderer.xml
+++ b/addons/web/static/src/views/list/list_renderer.xml
@@ -24,6 +24,7 @@
t-att-class="getColumnClass(column) + ' opacity-trigger-hover'"
t-on-mouseenter="ev => this.onHoverSortColumn(ev, column)"
t-on-mouseleave="ev => this.onHoverSortColumn(ev, column)"
+ t-on-mouseup="onColumnTitleMouseUp"
t-on-click="() => this.onClickSortColumn(column)"
t-on-keydown.synthetic="(ev) => this.onCellKeydown(ev)" t-att-data-tooltip-template="isDebugMode ? 'web.FieldTooltip' : false" t-att-data-tooltip-info="isDebugMode ? makeTooltip(column) : false"
tabindex="-1">
@@ -37,7 +38,6 @@
diff --git a/addons/web/static/tests/views/list_view_tests.js b/addons/web/static/tests/views/list_view_tests.js
index 7e801c416c4..8d8c2ed3efb 100644
--- a/addons/web/static/tests/views/list_view_tests.js
+++ b/addons/web/static/tests/views/list_view_tests.js
@@ -23,6 +23,7 @@ import {
clickOpenedDropdownItem,
clickOpenM2ODropdown,
clickSave,
+ drag,
dragAndDrop,
editInput,
editSelect,
@@ -14869,6 +14870,59 @@ QUnit.module("Views", (hooks) => {
);
});
+ QUnit.test("list: column: resize, reorder, resize again", async function (assert) {
+ serverData.models.foo.fields.foo.sortable = true;
+ serverData.models.foo.fields.int_field.sortable = true;
+ await makeView({
+ type: "list",
+ resModel: "foo",
+ serverData,
+ arch: `
+
+
+
+ `,
+ });
+
+ // pointer doesn't perfectly match the resized th.
+ const PIXEL_TOLERANCE = 3;
+ const assertAlmostEqual = (v1, v2) => Math.abs(v1 - v2) <= PIXEL_TOLERANCE;
+
+ // 1. Resize column foo to middle of column int_field.
+ const originalWidths = [...target.querySelectorAll(".o_list_table th")].map(
+ (th) => th.offsetWidth
+ );
+ const th2 = target.querySelector("th:nth-child(2)");
+ const th3 = target.querySelector("th:nth-child(3)");
+ const resizeHandle = th2.querySelector(".o_resize");
+
+ await dragAndDrop(resizeHandle, th3);
+
+ const widthsAfterResize = [...target.querySelectorAll(".o_list_table th")].map(
+ (th) => th.offsetWidth
+ );
+
+ assert.strictEqual(widthsAfterResize[0], originalWidths[0]);
+ assertAlmostEqual(widthsAfterResize[1], originalWidths[1] + originalWidths[2] / 2);
+
+ // 2. Reorder column foo.
+ await click(th2);
+ const widthsAfterReorder = [...target.querySelectorAll(".o_list_table th")].map(
+ (th) => th.offsetWidth
+ );
+
+ assert.strictEqual(widthsAfterResize[0], widthsAfterReorder[0]);
+ assert.strictEqual(widthsAfterResize[1], widthsAfterReorder[1]);
+
+ // 3. Resize again, this time check sizes while dragging and after drop.
+ const drop = drag(resizeHandle, th3);
+ assertAlmostEqual(th2.offsetWidth, widthsAfterReorder[1] + widthsAfterReorder[2] / 2);
+
+ drop();
+ await nextTick();
+ assertAlmostEqual(th2.offsetWidth, widthsAfterReorder[1] + widthsAfterReorder[2] / 2);
+ });
+
QUnit.test("editable list: resize column headers", async function (assert) {
await makeView({
type: "list",