Skip to content

feat: Add resizing for QTable Columns: Issue #5115 #17838

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
163 changes: 105 additions & 58 deletions ui/src/components/table/QTable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { h, ref, computed, watch, getCurrentInstance } from 'vue'
import { h, ref, computed, watch, getCurrentInstance, onMounted, reactive } from 'vue'

import QTh from './QTh.js'

Expand Down Expand Up @@ -43,10 +43,12 @@ export default createComponent({
type: [ String, Function ],
default: 'id'
},

resizableCols: Boolean,
columns: Array,
loading: Boolean,



iconFirstPage: String,
iconPrevPage: String,
iconNextPage: String,
Expand Down Expand Up @@ -127,6 +129,48 @@ export default createComponent({
const vm = getCurrentInstance()
const { proxy: { $q } } = vm

const colWidths = reactive({})
const resizingCol = ref(null)
const startX = ref(0)

onMounted(() => {
props.columns.forEach(col => {
colWidths[col.name] = 150
})
})

function resetColumnWidth (colName) {
colWidths[colName] = 150 // Reset to default width or any desired full size
}

function startResizing (colName, evt) {
resizingCol.value = colName
startX.value = evt.pageX
document.addEventListener('mousemove', handleResize)
document.addEventListener('mouseup', stopResizing)
}

function handleResize (evt) {
if (!resizingCol.value) return
const diff = evt.pageX - startX.value
colWidths[resizingCol.value] += diff
startX.value = evt.pageX
}

function stopResizing () {
document.removeEventListener('mousemove', handleResize)
document.removeEventListener('mouseup', stopResizing)
resizingCol.value = null
}

return {
colWidths,
resetColumnWidth,
startResizing,
handleResize,
stopResizing,
};

const isDark = useDark(props, $q)
const { inFullscreen, toggleFullscreen } = useFullscreen()

Expand Down Expand Up @@ -621,62 +665,65 @@ export default createComponent({
return h('thead', child)
}

function getTHeadTR () {
const
header = slots.header,
headerCell = slots[ 'header-cell' ]

if (header !== void 0) {
return header(
getHeaderScope({ header: true })
).slice()
}

const child = computedCols.value.map(col => {
const
headerCellCol = slots[ `header-cell-${ col.name }` ],
slot = headerCellCol !== void 0 ? headerCellCol : headerCell,
props = getHeaderScope({ col })

return slot !== void 0
? slot(props)
: h(QTh, {
key: col.name,
props
}, () => col.label)
})

if (singleSelection.value === true && props.grid !== true) {
child.unshift(
h('th', { class: 'q-table--col-auto-width' }, ' ')
)
}
else if (multipleSelection.value === true) {
const slot = slots[ 'header-selection' ]
const content = slot !== void 0
? slot(getHeaderScope({}))
: [
h(QCheckbox, {
color: props.color,
modelValue: headerSelectedValue.value,
dark: isDark.value,
dense: props.dense,
'onUpdate:modelValue': onMultipleSelectionSet
})
]

child.unshift(
h('th', { class: 'q-table--col-auto-width' }, content)
)
}

return [
h('tr', {
class: props.tableHeaderClass,
style: props.tableHeaderStyle
}, child)
]
}
function getTHeadTR() {
const header = slots.header;
const headerCell = slots['header-cell'];

if (header !== void 0) {
return header(
getHeaderScope({ header: true })
).slice();
}

const child = computedCols.value.map(col => {
const headerCellCol = slots[`header-cell-${col.name}`];
const slot = headerCellCol !== void 0 ? headerCellCol : headerCell;
const props = getHeaderScope({ col });

return slot !== void 0
? slot(props)
: h(QTh, {
key: col.name,
props
}, () => [
col.label,
col.resizable ? h('div', {
class: 'q-table__resize-handle',
onMousedown: evt => startResizing(col.name, evt)
}) : null
]);
});

if (singleSelection.value === true && props.grid !== true) {
child.unshift(
h('th', { class: 'q-table--col-auto-width' }, ' ')
);
} else if (multipleSelection.value === true) {
const slot = slots['header-selection'];
const content = slot !== void 0
? slot(getHeaderScope({}))
: [
h(QCheckbox, {
color: props.color,
modelValue: headerSelectedValue.value,
dark: isDark.value,
dense: props.dense,
'onUpdate:modelValue': onMultipleSelectionSet
})
];

child.unshift(
h('th', { class: 'q-table--col-auto-width' }, content)
);
}

return [
h('tr', {
class: props.tableHeaderClass,
style: props.tableHeaderStyle
}, child)
];
}

function getHeaderScope (data) {
Object.assign(data, {
Expand Down
6 changes: 5 additions & 1 deletion ui/src/components/table/QTable.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@
"examples": [ "# :rows=\"myData\"" ],
"category": "general"
},

"resizable-cols": {
"type": "Boolean",
"desc": "Enabling allows for easy configuration of user resizable column widths by adding a customizable drag handle between each column specified in the 'columns' prop. By default the drag handle is a small vertical line between each column. The drag handle can be customized by using the 'column-resize-handle' slot. Double clicking the grabber sets the columns back to their default width",
"category": "behavior"
},
"row-key": {
"type": [ "String", "Function" ],
"desc": "Property of each row that defines the unique key of each row (the result must be a primitive, not Object, Array, etc); The value of property must be string or a function taking a row and returning the desired (nested) key in the row; If supplying a function then for best performance, reference it from your scope and do not define it inline",
Expand Down
13 changes: 13 additions & 0 deletions ui/src/components/table/QTable.sass
Original file line number Diff line number Diff line change
Expand Up @@ -291,3 +291,16 @@ body.desktop .q-table > tbody > tr:not(.q-tr--no-hover):hover > td:not(.q-td--no
&.q-table--vertical-separator, &.q-table--cell-separator
.q-table__top
border-color: $table-dark-border-color



.q-table th .q-table__resize-handle {
cursor: col-resize
display: inline-block
width: 6px
height: 100%
background-color: #ccc
position: absolute
right: 0
top: 0
}