✨ feat (pub): adjust data table
This commit is contained in:
@@ -13,6 +13,12 @@ const props = defineProps<{
|
||||
funcParsed: RecStrFuncUnknown
|
||||
funcHtml: RecStrFuncUnknown
|
||||
funcComponent: RecStrFuncComponent
|
||||
selectMode?: 'single' | 'multiple'
|
||||
modelValue?: any[] | any
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', val: any[] | any): void
|
||||
}>()
|
||||
|
||||
const getSkeletonSize = computed(() => {
|
||||
@@ -20,6 +26,24 @@ const getSkeletonSize = computed(() => {
|
||||
})
|
||||
const loader = inject('table_data_loader') as DataTableLoader
|
||||
|
||||
// local state utk selection
|
||||
const selected = ref<any[]>([])
|
||||
|
||||
function toggleSelection(row: any) {
|
||||
if (props.selectMode === 'single') {
|
||||
selected.value = [row]
|
||||
emit('update:modelValue', row)
|
||||
} else {
|
||||
const idx = selected.value.findIndex((r) => r === row)
|
||||
if (idx >= 0) {
|
||||
selected.value.splice(idx, 1)
|
||||
} else {
|
||||
selected.value.push(row)
|
||||
}
|
||||
emit('update:modelValue', [...selected.value])
|
||||
}
|
||||
}
|
||||
|
||||
function handleActionCellClick(event: Event, _cellRef: string) {
|
||||
// Prevent event if clicked directly on the button/dropdown
|
||||
const target = event.target as HTMLElement
|
||||
@@ -70,32 +94,38 @@ function handleActionCellClick(event: Event, _cellRef: string) {
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
<TableBody v-else>
|
||||
<TableRow v-for="(row, rowIndex) in rows" :key="`row-${rowIndex}`">
|
||||
<TableCell
|
||||
v-for="(key, cellIndex) in keys"
|
||||
:key="`cell-${rowIndex}-${cellIndex}`"
|
||||
class="border"
|
||||
:class="{ 'cursor-pointer': key === 'action' && funcComponent[key] }"
|
||||
@click="
|
||||
key === 'action' && funcComponent[key]
|
||||
? handleActionCellClick($event, `cell-${rowIndex}-${cellIndex}`)
|
||||
: null
|
||||
"
|
||||
>
|
||||
<!-- If funcComponent has a renderer -->
|
||||
<TableRow
|
||||
v-for="(row, rowIndex) in rows"
|
||||
:key="`row-${rowIndex}`"
|
||||
:class="{
|
||||
'bg-green-50': props.selectMode === 'single' && selected.includes(row),
|
||||
'bg-blue-50': props.selectMode === 'multiple' && selected.includes(row),
|
||||
}"
|
||||
@click="toggleSelection(row)"
|
||||
>
|
||||
<!-- opsional: kalau mau tampilkan checkbox/radio di cell pertama -->
|
||||
<TableCell v-if="props.selectMode">
|
||||
<input
|
||||
v-if="props.selectMode === 'single'"
|
||||
type="radio"
|
||||
:checked="selected.includes(row)"
|
||||
@change="toggleSelection(row)"
|
||||
/>
|
||||
<input v-else type="checkbox" :checked="selected.includes(row)" @change="toggleSelection(row)" />
|
||||
</TableCell>
|
||||
|
||||
<!-- lanjut render cell normal -->
|
||||
<TableCell v-for="(key, cellIndex) in keys" :key="`cell-${rowIndex}-${cellIndex}`" class="border">
|
||||
<!-- existing cell renderer -->
|
||||
<component
|
||||
:is="funcComponent[key]?.(row, rowIndex).component"
|
||||
v-if="funcComponent[key]"
|
||||
:ref="key === 'action' ? `actionComponent-${rowIndex}-${cellIndex}` : undefined"
|
||||
:rec="row"
|
||||
:idx="rowIndex"
|
||||
v-bind="funcComponent[key]?.(row, rowIndex).props"
|
||||
/>
|
||||
<!-- If funcParsed or funcHtml returns a value -->
|
||||
<template v-else>
|
||||
<!-- Use v-html for funcHtml to render HTML content -->
|
||||
<div v-if="funcHtml[key]" v-html="funcHtml[key]?.(row, rowIndex)"></div>
|
||||
<!-- Use normal interpolation for funcParsed and regular data -->
|
||||
<template v-else>
|
||||
{{ funcParsed[key]?.(row, rowIndex) ?? (row as any)[key] }}
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user