Created
June 10, 2021 16:03
-
-
Save IlCallo/795ddd07dfc6bb48519f3d81f670e77c to your computer and use it in GitHub Desktop.
Composable to manage sticky columns for QTable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.sticky-table .q-table { | |
th.sticky-cell, | |
td.sticky-cell { | |
position: sticky; | |
z-index: 1; | |
} | |
th.last-sticky-cell, | |
td.last-sticky-cell { | |
border-right: 2px solid rgba($color: black, $alpha: 0.12); | |
} | |
} | |
.sticky-table.alternate-row-color { | |
tr:nth-child(odd) { | |
// Sticky columns feature needs flat colors | |
background-color: #ffffff; | |
} | |
tr:nth-child(even) { | |
// Equal to: rgba($color: $primary, $alpha: 0.12) | |
// Calculated with http://marcodiiga.github.io/rgba-to-rgb-conversion | |
// Sticky columns feature needs flat colors | |
background-color: #eaebeb !important; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
onMounted, | |
onUnmounted, | |
onUpdated, | |
Ref, | |
watch | |
} from '@vue/composition-api'; | |
import { throttle } from 'lodash-es'; | |
import { QTable } from 'quasar'; | |
const STICKY_TABLE_CLASS = 'sticky-table'; | |
const STICKY_CELL_CLASS = 'sticky-cell'; | |
const LAST_STICKY_CELL_CLASS = `last-${STICKY_CELL_CLASS}`; | |
/** | |
* Make left-most columns sticky | |
* | |
* @param table Reactive reference to the table | |
* @param count Reactive reference to the number of columns to make sticky | |
* @returns The method which manually trigger the sticky columns update | |
*/ | |
export function useStickyColumns(table: Ref<QTable>, count: Ref<number>) { | |
let $el: Element; | |
function updateStickyColumns() { | |
// Must add back the class every time due to | |
// Vue "class" attribute reactive management which overwrites | |
// the value at every cycle | |
$el.classList.add(STICKY_TABLE_CLASS); | |
const stickyLeftValues: number[] = []; | |
$el | |
.querySelectorAll<HTMLElement>( | |
`.q-table th:nth-child(-n + ${count.value})` | |
) | |
.forEach((element, index) => { | |
const isLastStickyPerRow = index % count.value === count.value - 1; | |
const leftShift = index === 0 ? 0 : stickyLeftValues[index - 1]; | |
element.style.left = `${leftShift}px`; | |
element.classList.add(STICKY_CELL_CLASS); | |
isLastStickyPerRow && element.classList.add(LAST_STICKY_CELL_CLASS); | |
stickyLeftValues.push(leftShift + element.offsetWidth); | |
}); | |
$el | |
.querySelectorAll<HTMLElement>( | |
`.q-table td:nth-child(-n + ${count.value})` | |
) | |
.forEach((element, index) => { | |
const isLastStickyPerRow = index % count.value === count.value - 1; | |
const relativeIndex = index % count.value; | |
element.style.left = `${ | |
relativeIndex === 0 ? 0 : stickyLeftValues[relativeIndex - 1] | |
}px`; | |
element.classList.add(STICKY_CELL_CLASS); | |
isLastStickyPerRow && element.classList.add(LAST_STICKY_CELL_CLASS); | |
}); | |
} | |
const throttledUpdate = throttle(updateStickyColumns, 100); | |
onMounted(() => { | |
$el = table.value.$el as HTMLElement; | |
window.addEventListener('resize', throttledUpdate); | |
}); | |
onUnmounted(() => { | |
window.removeEventListener('resize', throttledUpdate); | |
}); | |
onUpdated(updateStickyColumns); | |
watch(count, () => { | |
// Cleanup classes related to previous count value | |
$el | |
.querySelectorAll<HTMLElement>(`.q-table .${STICKY_CELL_CLASS}`) | |
.forEach(element => | |
element.classList.remove(STICKY_CELL_CLASS, LAST_STICKY_CELL_CLASS) | |
); | |
updateStickyColumns(); | |
}); | |
return { updateStickyColumns }; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const tableRef = ref() as Ref<QTable>; | |
const stickyColumnCount = ref(4); | |
useStickyColumns(tableRef, stickyColumnCount); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment