feat: enhance RowDeleteAction and useDestroy for reactive URL handling; add rowKey prop to DataTable

This commit is contained in:
Yoga Pangestu 2026-07-27 18:51:37 +07:00
parent 399b444b54
commit ec8cb94486
4 changed files with 21 additions and 4 deletions

View File

@ -1,5 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { Trash2 } from '@lucide/vue'; import { Trash2 } from '@lucide/vue';
import { toRef } from 'vue';
import ConfirmDialog from '@/components/ConfirmDialog.vue'; import ConfirmDialog from '@/components/ConfirmDialog.vue';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'; import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
@ -19,7 +20,7 @@ const props = defineProps<{
}>(); }>();
const { open, processing, destroy } = useDestroy({ const { open, processing, destroy } = useDestroy({
url: props.actionUrl, url: toRef(props, 'actionUrl'),
errorMessage: props.errorMessage ?? 'Gagal menghapus data.', errorMessage: props.errorMessage ?? 'Gagal menghapus data.',
onSuccess: props.onSuccess, onSuccess: props.onSuccess,
onError: props.onError, onError: props.onError,

View File

@ -37,6 +37,7 @@ const props = withDefaults(
paginationDisplayedCount?: number; paginationDisplayedCount?: number;
paginationItemLabel?: string; paginationItemLabel?: string;
getRowClassName?: (row: TData, index: number) => string | undefined; getRowClassName?: (row: TData, index: number) => string | undefined;
rowKey?: string | ((row: TData, index: number) => string | number);
loading?: boolean; loading?: boolean;
}>(), }>(),
{ {
@ -76,6 +77,18 @@ const resolvedColumns = computed(() => (
props.showRowNumber ? [rowNumberColumn, ...props.columns] : props.columns props.showRowNumber ? [rowNumberColumn, ...props.columns] : props.columns
)); ));
function getRowId(row: TData, index: number): string {
if (!props.rowKey) {
return String(index);
}
if (typeof props.rowKey === 'function') {
return String(props.rowKey(row, index));
}
return String((row as Record<string, unknown>)[props.rowKey as string]);
}
const table = useVueTable({ const table = useVueTable({
get data() { get data() {
return props.data; return props.data;
@ -85,6 +98,7 @@ const table = useVueTable({
}, },
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
manualSorting: true, manualSorting: true,
getRowId,
}); });
function handleSort(column: string): void { function handleSort(column: string): void {

View File

@ -1,9 +1,9 @@
import { router } from '@inertiajs/vue3'; import { router } from '@inertiajs/vue3';
import { ref } from 'vue'; import { computed, ref, type Ref } from 'vue';
import { toast } from 'vue-sonner'; import { toast } from 'vue-sonner';
interface UseDestroyOptions { interface UseDestroyOptions {
url: string; url: string | Ref<string>;
preserveScroll?: boolean; preserveScroll?: boolean;
errorMessage?: string; errorMessage?: string;
onSuccess?: () => void; onSuccess?: () => void;
@ -13,11 +13,12 @@ interface UseDestroyOptions {
export function useDestroy({ url, preserveScroll = true, errorMessage, onSuccess, onError }: UseDestroyOptions) { export function useDestroy({ url, preserveScroll = true, errorMessage, onSuccess, onError }: UseDestroyOptions) {
const open = ref(false); const open = ref(false);
const processing = ref(false); const processing = ref(false);
const resolvedUrl = computed(() => (typeof url === 'string' ? url : url.value));
function destroy() { function destroy() {
processing.value = true; processing.value = true;
router.delete(url, { router.delete(resolvedUrl.value, {
preserveScroll, preserveScroll,
onSuccess: () => { onSuccess: () => {
open.value = false; open.value = false;

View File

@ -107,6 +107,7 @@ watch(
:pagination="pagination" :pagination="pagination"
:pagination-links="categories.links" :pagination-links="categories.links"
:sort="currentSort" :sort="currentSort"
row-key="id"
@sort-change="setSort" @sort-change="setSort"
@filters-reset="resetFilters" @filters-reset="resetFilters"
/> />