292 lines
6.6 KiB
Markdown
292 lines
6.6 KiB
Markdown
# 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:
|
|
```vue
|
|
<FlexRender
|
|
:render="cell.column.columnDef.cell"
|
|
:props="cell.getContext()"
|
|
/>
|
|
```
|
|
|
|
### 2. **Better Column Definitions**
|
|
Supports both simple and advanced formats:
|
|
|
|
**Simple:**
|
|
```javascript
|
|
{ key: 'name', label: 'Name', sortable: true }
|
|
```
|
|
|
|
**Advanced:**
|
|
```javascript
|
|
{
|
|
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:
|
|
```javascript
|
|
onSortingChange: (updater) => valueUpdater(updater, sorting)
|
|
```
|
|
|
|
## Migration Steps
|
|
|
|
### Step 1: Update Imports
|
|
|
|
**Before:**
|
|
```vue
|
|
import DataTable from '@/Components/DataTable/DataTable.vue';
|
|
```
|
|
|
|
**After:**
|
|
```vue
|
|
import DataTable from '@/Components/DataTable/DataTableNew2.vue';
|
|
```
|
|
|
|
### Step 2: Update Props
|
|
|
|
**Before:**
|
|
```vue
|
|
<DataTable
|
|
:rows="clients.data"
|
|
:columns="columns"
|
|
:meta="clients.meta"
|
|
/>
|
|
```
|
|
|
|
**After:**
|
|
```vue
|
|
<DataTable
|
|
:data="clients.data"
|
|
:columns="columns"
|
|
:meta="clients.meta"
|
|
route-name="clients.index"
|
|
/>
|
|
```
|
|
|
|
Main prop changes:
|
|
- `rows` → `data`
|
|
- Add `route-name` for server-side pagination
|
|
|
|
### Step 3: Column Definitions
|
|
|
|
Your existing simple column format still works:
|
|
```javascript
|
|
const columns = [
|
|
{ key: 'id', label: 'ID', sortable: true },
|
|
{ key: 'name', label: 'Name', sortable: true },
|
|
];
|
|
```
|
|
|
|
But you can now use advanced format for more control:
|
|
```javascript
|
|
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!
|
|
|
|
```vue
|
|
<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)
|
|
|
|
```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)
|
|
|
|
```vue
|
|
<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:
|
|
```javascript
|
|
import { FlexRender } from '@tanstack/vue-table';
|
|
```
|
|
|
|
### Issue: Column not sorting
|
|
**Solution:** Make sure `sortable: true` is set:
|
|
```javascript
|
|
{ key: 'name', label: 'Name', sortable: true }
|
|
```
|
|
|
|
### Issue: Server-side not working
|
|
**Solution:** Provide both `meta` and `route-name`:
|
|
```vue
|
|
<DataTable
|
|
:data="data"
|
|
:meta="meta"
|
|
route-name="your.route.name"
|
|
/>
|
|
```
|
|
|
|
### Issue: Custom cells not rendering
|
|
**Solution:** Use the correct slot name format:
|
|
```vue
|
|
<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:
|
|
```vue
|
|
import DataTable from '@/Components/DataTable/DataTable.vue';
|
|
// or
|
|
import DataTableServer from '@/Components/DataTable/DataTableServer.vue';
|
|
```
|
|
|
|
Nothing breaks your existing code!
|