I've got a table with table-layout="auto" for autowidth of the columns, and height=400 for the fixed header, but the scroll overflows the header which should not happen.
With table-layout="fixed" the scroll will fix, but the columns will not get all the width. It uses Vue3 and the library component element plus.
<template>
<el-table
height="400"
:data="internalData"
:default-sort="defaultSort"
@sort-change="$emit('sort-change', $event)"
style="width: 100%"
border
class="custom-table"
table-layout="fixed"
overflow-x="auto"
@row-click="handleRowClick"
>
<el-table-column
v-for="col in columns"
:key="col.prop"
:prop="col.prop"
:label="col.label"
:width="col.width"
:min-width="col.minWidth"
:sortable="col.sortable ? 'custom' : false"
>
</el-table-column>
</el-table>
</template>
<script setup lang="ts">
import { ref, onBeforeMount, watch } from 'vue'
// Define props and emits (añadà desync para debugging)
const props = defineProps<{
data: Record<string, any>[],
columns: any[],
desync?: boolean
}>()
defineEmits(['sort-change'])
const handleRowClick = (row: any) => {
console.log(row)
}
// defaultSort definido antes del render
const defaultSort = ref({
prop: 'id',
order: 'ascending' as 'ascending' | 'descending' | null, // Element Plus usa 'ascending'/'descending'
})
// datos internos que usa la tabla (permite simular desincronÃa)
const internalData = ref<Record<string, any>[]>([])
function applySort(arr: Record<string, any>[], sort: { prop?: string; order?: string | null }) {
if (!sort?.prop || !sort.order) return
const prop = sort.prop
const order = sort.order === 'ascending' ? 1 : -1
arr.sort((a, b) => {
if (a[prop] == null) return 1 * order
if (b[prop] == null) return -1 * order
if (a[prop] > b[prop]) return 1 * order
if (a[prop] < b[prop]) return -1 * order
return 0
})
}
function shuffle(arr: Record<string, any>[]) {
// Fisher–Yates
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
;[arr[i], arr[j]] = [arr[j], arr[i]]
}
}
// inicializar antes del primer render
onBeforeMount(() => {
internalData.value = props.data ? [...props.data] : []
if (props.desync) {
// para reproducir el bug: la UI se muestra en orden distinto al sort por defecto
shuffle(internalData.value)
// mantiene defaultSort para la cabecera pero la lista mostrada está desordenada
} else {
// aplicar sort por defecto antes del render para evitar flicker
applySort(internalData.value, defaultSort.value)
}
})
// si los datos externos cambian, sincronizar respetando el modo desync
watch(
() => props.data,
(newData) => {
internalData.value = newData ? [...newData] : []
if (props.desync) {
shuffle(internalData.value)
} else {
applySort(internalData.value, defaultSort.value)
}
},
{ immediate: false }
)
</script>
<style scoped>
:deep(.cell) {
white-space: nowrap !important;
}
</style>
How can I fix it? I need a mix between table-layout="fixed" and table-layout="auto" for full width columns.