From 502b8352f152af88f4351b311b962ad2067c3788 Mon Sep 17 00:00:00 2001 From: mertsincan Date: Tue, 19 Dec 2023 11:48:00 +0000 Subject: [PATCH] Fixed #2188 - DataTable Column Resizing incompatible with Column Reordering --- components/lib/datatable/DataTable.vue | 99 +++++++++++++++++-------- components/lib/datatable/HeaderCell.vue | 8 +- 2 files changed, 71 insertions(+), 36 deletions(-) diff --git a/components/lib/datatable/DataTable.vue b/components/lib/datatable/DataTable.vue index e7fd50923..3cbd14cae 100755 --- a/components/lib/datatable/DataTable.vue +++ b/components/lib/datatable/DataTable.vue @@ -360,6 +360,7 @@ export default { colReorderIconWidth: null, colReorderIconHeight: null, draggedColumn: null, + draggedColumnElement: null, draggedRowIndex: null, droppedRowIndex: null, rowDragging: null, @@ -1337,7 +1338,9 @@ export default { else event.currentTarget.draggable = true; } }, - onColumnHeaderDragStart(event) { + onColumnHeaderDragStart(e) { + const { originalEvent: event, column } = e; + if (this.columnResizing) { event.preventDefault(); @@ -1347,18 +1350,20 @@ export default { this.colReorderIconWidth = DomHandler.getHiddenElementOuterWidth(this.$refs.reorderIndicatorUp); this.colReorderIconHeight = DomHandler.getHiddenElementOuterHeight(this.$refs.reorderIndicatorUp); - this.draggedColumn = this.findParentHeader(event.target); + this.draggedColumn = column; + this.draggedColumnElement = this.findParentHeader(event.target); event.dataTransfer.setData('text', 'b'); // Firefox requires this to make dragging possible }, - onColumnHeaderDragOver(event) { + onColumnHeaderDragOver(e) { + const { originalEvent: event, column } = e; let dropHeader = this.findParentHeader(event.target); - if (this.reorderableColumns && this.draggedColumn && dropHeader) { + if (this.reorderableColumns && this.draggedColumnElement && dropHeader && !this.columnProp(column, 'frozen')) { event.preventDefault(); let containerOffset = DomHandler.getOffset(this.$el); let dropHeaderOffset = DomHandler.getOffset(dropHeader); - if (this.draggedColumn !== dropHeader) { + if (this.draggedColumnElement !== dropHeader) { let targetLeft = dropHeaderOffset.left - containerOffset.left; let columnCenter = dropHeaderOffset.left + dropHeader.offsetWidth / 2; @@ -1380,18 +1385,22 @@ export default { } } }, - onColumnHeaderDragLeave(event) { - if (this.reorderableColumns && this.draggedColumn) { + onColumnHeaderDragLeave(e) { + const { originalEvent: event } = e; + + if (this.reorderableColumns && this.draggedColumnElement) { event.preventDefault(); this.$refs.reorderIndicatorUp.style.display = 'none'; this.$refs.reorderIndicatorDown.style.display = 'none'; } }, - onColumnHeaderDrop(event) { + onColumnHeaderDrop(e) { + const { originalEvent: event, column } = e; + event.preventDefault(); - if (this.draggedColumn) { - let dragIndex = DomHandler.index(this.draggedColumn); + if (this.draggedColumnElement) { + let dragIndex = DomHandler.index(this.draggedColumnElement); let dropIndex = DomHandler.index(this.findParentHeader(event.target)); let allowDrop = dragIndex !== dropIndex; @@ -1400,19 +1409,42 @@ export default { } if (allowDrop) { - ObjectUtils.reorderArray(this.columns, dragIndex, dropIndex); + let isSameColumn = (col1, col2) => + this.columnProp(col1, 'columnKey') || this.columnProp(col2, 'columnKey') ? this.columnProp(col1, 'columnKey') === this.columnProp(col2, 'columnKey') : this.columnProp(col1, 'field') === this.columnProp(col2, 'field'); + let dragColIndex = this.columns.findIndex((child) => isSameColumn(child, this.draggedColumn)); + let dropColIndex = this.columns.findIndex((child) => isSameColumn(child, column)); + let widths = []; + let headers = DomHandler.find(this.$el, 'thead[data-pc-section="thead"] > tr > th'); + + headers.forEach((header) => widths.push(DomHandler.getOuterWidth(header))); + const movedItem = widths.find((_, index) => index === dragColIndex); + const remainingItems = widths.filter((_, index) => index !== dragColIndex); + const reorderedWidths = [...remainingItems.slice(0, dropColIndex), movedItem, ...remainingItems.slice(dropColIndex)]; + + this.addColumnWidthStyles(reorderedWidths); + + if (dropColIndex < dragColIndex && this.dropPosition === 1) { + dropColIndex++; + } + + if (dropColIndex > dragColIndex && this.dropPosition === -1) { + dropColIndex--; + } + + ObjectUtils.reorderArray(this.columns, dragColIndex, dropColIndex); this.updateReorderableColumns(); this.$emit('column-reorder', { originalEvent: event, - dragIndex: dragIndex, - dropIndex: dropIndex + dragIndex: dragColIndex, + dropIndex: dropColIndex }); } this.$refs.reorderIndicatorUp.style.display = 'none'; this.$refs.reorderIndicatorDown.style.display = 'none'; - this.draggedColumn.draggable = false; + this.draggedColumnElement.draggable = false; + this.draggedColumnElement = null; this.draggedColumn = null; this.dropPosition = null; } @@ -1714,6 +1746,26 @@ export default { state.tableWidth = DomHandler.getOuterWidth(this.$refs.table) + 'px'; } }, + addColumnWidthStyles(widths) { + this.createStyleElement(); + + let innerHTML = ''; + let selector = `[data-pc-name="datatable"][${this.attributeSelector}] > [data-pc-section="wrapper"] ${this.virtualScrollerDisabled ? '' : '> [data-pc-name="virtualscroller"]'} > table[data-pc-section="table"]`; + + widths.forEach((width, index) => { + let style = `width: ${width}px !important; max-width: ${width}px !important`; + + innerHTML += ` + ${selector} > thead[data-pc-section="thead"] > tr > th:nth-child(${index + 1}), + ${selector} > tbody[data-pc-section="tbody"] > tr > td:nth-child(${index + 1}), + ${selector} > tfoot[data-pc-section="tfoot"] > tr > td:nth-child(${index + 1}) { + ${style} + } + `; + }); + + this.styleElement.innerHTML = innerHTML; + }, restoreColumnWidths() { if (this.columnWidthsState) { let widths = this.columnWidthsState.split(','); @@ -1725,24 +1777,7 @@ export default { } if (ObjectUtils.isNotEmpty(widths)) { - this.createStyleElement(); - - let innerHTML = ''; - let selector = `[data-pc-name="datatable"][${this.attributeSelector}] > [data-pc-section="wrapper"] ${this.virtualScrollerDisabled ? '' : '> [data-pc-name="virtualscroller"]'} > table[data-pc-section="table"]`; - - widths.forEach((width, index) => { - let style = `width: ${width}px !important; max-width: ${width}px !important`; - - innerHTML += ` - ${selector} > thead[data-pc-section="thead"] > tr > th:nth-child(${index + 1}), - ${selector} > tbody[data-pc-section="tbody"] > tr > td:nth-child(${index + 1}), - ${selector} > tfoot[data-pc-section="tfoot"] > tr > td:nth-child(${index + 1}) { - ${style} - } - `; - }); - - this.styleElement.innerHTML = innerHTML; + this.addColumnWidthStyles(widths); } } }, diff --git a/components/lib/datatable/HeaderCell.vue b/components/lib/datatable/HeaderCell.vue index b1050b389..adcf7aa16 100644 --- a/components/lib/datatable/HeaderCell.vue +++ b/components/lib/datatable/HeaderCell.vue @@ -237,16 +237,16 @@ export default { this.$emit('column-mousedown', { originalEvent: event, column: this.column }); }, onDragStart(event) { - this.$emit('column-dragstart', event); + this.$emit('column-dragstart', { originalEvent: event, column: this.column }); }, onDragOver(event) { - this.$emit('column-dragover', event); + this.$emit('column-dragover', { originalEvent: event, column: this.column }); }, onDragLeave(event) { - this.$emit('column-dragleave', event); + this.$emit('column-dragleave', { originalEvent: event, column: this.column }); }, onDrop(event) { - this.$emit('column-drop', event); + this.$emit('column-drop', { originalEvent: event, column: this.column }); }, onResizeStart(event) { this.$emit('column-resizestart', event);