Teren-app/resources/js/Components/DataTable/MIGRATION.md
2025-11-20 18:11:43 +01:00

6.6 KiB

DataTable Migration Guide

Summary of Changes

The DataTable component has been updated to follow shadcn-vue architecture patterns using TanStack Table v8. This provides better flexibility, more features, and follows industry-standard patterns.

What's New

Components Created/Updated

  1. DataTableNew2.vue - New main component with shadcn-vue architecture
  2. DataTableColumnHeader.vue - Already good, uses lucide-vue-next icons
  3. DataTablePagination.vue - Already follows shadcn-vue patterns
  4. DataTableViewOptions.vue - Already follows shadcn-vue patterns
  5. DataTableToolbar.vue - Already exists with advanced features
  6. columns-example.js - Column definition examples
  7. README.md - Comprehensive documentation
  8. DataTableExample.vue - Working example page

Utilities Added

  • valueUpdater() in lib/utils.js - Helper for TanStack Table state management

Key Improvements

1. FlexRender Integration

Now properly uses TanStack Table's FlexRender for column headers and cells:

<FlexRender 
  :render="cell.column.columnDef.cell" 
  :props="cell.getContext()" 
/>

2. Better Column Definitions

Supports both simple and advanced formats:

Simple:

{ key: 'name', label: 'Name', sortable: true }

Advanced:

{
  accessorKey: 'name',
  header: ({ column }) => h(DataTableColumnHeader, { column, title: 'Name' }),
  cell: ({ row }) => h('div', {}, row.getValue('name')),
}

3. Enhanced Features

  • Row selection with checkboxes
  • Column visibility toggle
  • Advanced filtering
  • Better loading/empty states
  • Custom cell slots
  • Flexible toolbar

4. Better State Management

Uses valueUpdater() helper for proper Vue reactivity with TanStack Table:

onSortingChange: (updater) => valueUpdater(updater, sorting)

Migration Steps

Step 1: Update Imports

Before:

import DataTable from '@/Components/DataTable/DataTable.vue';

After:

import DataTable from '@/Components/DataTable/DataTableNew2.vue';

Step 2: Update Props

Before:

<DataTable
  :rows="clients.data"
  :columns="columns"
  :meta="clients.meta"
/>

After:

<DataTable
  :data="clients.data"
  :columns="columns"
  :meta="clients.meta"
  route-name="clients.index"
/>

Main prop changes:

  • rowsdata
  • Add route-name for server-side pagination

Step 3: Column Definitions

Your existing simple column format still works:

const columns = [
  { key: 'id', label: 'ID', sortable: true },
  { key: 'name', label: 'Name', sortable: true },
];

But you can now use advanced format for more control:

import { h } from 'vue';
import DataTableColumnHeader from '@/Components/DataTable/DataTableColumnHeader.vue';

const columns = [
  {
    accessorKey: 'name',
    header: ({ column }) => h(DataTableColumnHeader, { column, title: 'Name' }),
    cell: ({ row }) => h('div', { class: 'font-medium' }, row.getValue('name')),
  },
];

Step 4: Custom Cell Rendering

Before: Required editing component After: Use slots!

<DataTable :columns="columns" :data="data">
  <template #cell-status="{ value, row }">
    <Badge :variant="value === 'active' ? 'default' : 'secondary'">
      {{ value }}
    </Badge>
  </template>
</DataTable>

Backward Compatibility

The old DataTable components are still available:

  • DataTable.vue - Your current enhanced version
  • DataTableServer.vue - Your server-side version
  • DataTableOld.vue - Original version

You can migrate pages gradually. Both old and new can coexist.

Example Migration

Before (Client/Index.vue)

<script setup>
import DataTable from '@/Components/DataTable/DataTable.vue';

const props = defineProps({
  clients: Object,
  filters: Object,
});

const columns = [
  { key: 'name', label: 'Name', sortable: true },
  { key: 'email', label: 'Email', sortable: true },
];
</script>

<template>
  <DataTable
    :rows="clients.data"
    :columns="columns"
    :meta="clients.meta"
    :search="filters.search"
    :sort="filters.sort"
    route-name="clients.index"
  />
</template>

After (Using DataTableNew2)

<script setup>
import DataTable from '@/Components/DataTable/DataTableNew2.vue';

const props = defineProps({
  clients: Object,
  filters: Object,
});

const columns = [
  { key: 'name', label: 'Name', sortable: true },
  { key: 'email', label: 'Email', sortable: true },
  { key: 'status', label: 'Status', sortable: false },
];
</script>

<template>
  <DataTable
    :data="clients.data"
    :columns="columns"
    :meta="clients.meta"
    :search="filters.search"
    :sort="filters.sort"
    route-name="clients.index"
    filter-column="email"
    filter-placeholder="Search clients..."
    :only-props="['clients']"
  >
    <!-- Add custom cell rendering -->
    <template #cell-status="{ value }">
      <Badge :variant="value === 'active' ? 'default' : 'secondary'">
        {{ value }}
      </Badge>
    </template>
  </DataTable>
</template>

Testing Your Migration

  1. Check the example page:

    Visit: /examples/datatable
    

    (You'll need to add a route for this)

  2. Test features:

    • Sorting (click column headers)
    • Filtering (use search input)
    • Pagination (navigate pages)
    • Row selection (if enabled)
    • Column visibility (View button)
  3. Check browser console:

    • No errors
    • Events firing correctly

Common Issues

Issue: "FlexRender is not defined"

Solution: Make sure you imported it:

import { FlexRender } from '@tanstack/vue-table';

Issue: Column not sorting

Solution: Make sure sortable: true is set:

{ key: 'name', label: 'Name', sortable: true }

Issue: Server-side not working

Solution: Provide both meta and route-name:

<DataTable
  :data="data"
  :meta="meta"
  route-name="your.route.name"
/>

Issue: Custom cells not rendering

Solution: Use the correct slot name format:

<template #cell-columnKey="{ value, row }">
  <!-- Your content -->
</template>

Need Help?

  1. Check README.md for detailed documentation
  2. Look at columns-example.js for column patterns
  3. Review DataTableExample.vue for working examples
  4. Check TanStack Table docs: https://tanstack.com/table/v8

Rollback Plan

If you encounter issues, you can always use the old components:

import DataTable from '@/Components/DataTable/DataTable.vue';
// or
import DataTableServer from '@/Components/DataTable/DataTableServer.vue';

Nothing breaks your existing code!