332 lines
8.8 KiB
Markdown
332 lines
8.8 KiB
Markdown
# DataTable Component Documentation
|
|
|
|
## Overview
|
|
|
|
A feature-rich data table component built with PrimeVue's DataTable. This component provides advanced functionality including pagination, sorting, filtering, row selection, and customizable column types with persistent filter state management.
|
|
|
|
## Basic Usage
|
|
|
|
```vue
|
|
<template>
|
|
<DataTable
|
|
:columns="tableColumns"
|
|
:data="tableData"
|
|
table-name="my-table"
|
|
@row-click="handleRowClick"
|
|
/>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
import DataTable from './components/common/DataTable.vue'
|
|
|
|
const tableColumns = ref([
|
|
{
|
|
fieldName: 'name',
|
|
label: 'Name',
|
|
sortable: true,
|
|
filterable: true
|
|
},
|
|
{
|
|
fieldName: 'status',
|
|
label: 'Status',
|
|
type: 'status',
|
|
sortable: true,
|
|
filterable: true
|
|
}
|
|
])
|
|
|
|
const tableData = ref([
|
|
{ id: 1, name: 'John Doe', status: 'completed' },
|
|
{ id: 2, name: 'Jane Smith', status: 'in progress' }
|
|
])
|
|
|
|
const handleRowClick = (event) => {
|
|
console.log('Row clicked:', event.data)
|
|
}
|
|
</script>
|
|
```
|
|
|
|
## Props
|
|
|
|
### `columns` (Array) - Required
|
|
- **Description:** Array of column configuration objects that define the table structure
|
|
- **Type:** `Array<Object>`
|
|
- **Required:** `true`
|
|
|
|
### `data` (Array) - Required
|
|
- **Description:** Array of data objects to display in the table
|
|
- **Type:** `Array<Object>`
|
|
- **Required:** `true`
|
|
|
|
### `tableName` (String) - Required
|
|
- **Description:** Unique identifier for the table, used for persistent filter state management
|
|
- **Type:** `String`
|
|
- **Required:** `true`
|
|
|
|
### `filters` (Object)
|
|
- **Description:** Initial filter configuration object
|
|
- **Type:** `Object`
|
|
- **Default:** `{ global: { value: null, matchMode: FilterMatchMode.CONTAINS } }`
|
|
|
|
## Column Configuration
|
|
|
|
Each column object in the `columns` array supports the following properties:
|
|
|
|
### Basic Properties
|
|
- **`fieldName`** (String, required) - The field name in the data object
|
|
- **`label`** (String, required) - Display label for the column header
|
|
- **`sortable`** (Boolean, default: `false`) - Enables sorting for this column
|
|
- **`filterable`** (Boolean, default: `false`) - Enables row-level filtering for this column
|
|
|
|
### Column Types
|
|
- **`type`** (String) - Defines special rendering behavior for the column
|
|
|
|
#### Available Types:
|
|
|
|
##### `'status'` Type
|
|
Renders values as colored tags/badges:
|
|
```javascript
|
|
{
|
|
fieldName: 'status',
|
|
label: 'Status',
|
|
type: 'status',
|
|
sortable: true,
|
|
filterable: true
|
|
}
|
|
```
|
|
|
|
**Status Colors:**
|
|
- `'completed'` → Success (green)
|
|
- `'in progress'` → Warning (yellow/orange)
|
|
- `'not started'` → Danger (red)
|
|
- Other values → Info (blue)
|
|
|
|
##### `'button'` Type
|
|
Renders values as clickable buttons:
|
|
```javascript
|
|
{
|
|
fieldName: 'action',
|
|
label: 'Action',
|
|
type: 'button'
|
|
}
|
|
```
|
|
|
|
## Events
|
|
|
|
### `rowClick`
|
|
- **Description:** Emitted when a button-type column is clicked
|
|
- **Payload:** PrimeVue slot properties object containing row data
|
|
- **Usage:** `@row-click="handleRowClick"`
|
|
|
|
```javascript
|
|
const handleRowClick = (slotProps) => {
|
|
console.log('Clicked row data:', slotProps.data)
|
|
console.log('Row index:', slotProps.index)
|
|
}
|
|
```
|
|
|
|
## Features
|
|
|
|
### Pagination
|
|
- **Rows per page options:** 5, 10, 20, 50
|
|
- **Default rows per page:** 10
|
|
- **Built-in pagination controls**
|
|
|
|
### Sorting
|
|
- **Multiple column sorting** support
|
|
- **Removable sort** - click to remove sort from a column
|
|
- **Sort indicators** in column headers
|
|
|
|
### Filtering
|
|
- **Row-level filtering** for filterable columns
|
|
- **Text-based search** with real-time filtering
|
|
- **Persistent filter state** across component re-renders
|
|
- **Global search capability**
|
|
|
|
### Selection
|
|
- **Multiple row selection** with checkboxes
|
|
- **Meta key selection** (Ctrl/Cmd + click for individual selection)
|
|
- **Unique row identification** using `dataKey="id"`
|
|
|
|
### Scrolling
|
|
- **Vertical scrolling** with fixed height (70vh)
|
|
- **Horizontal scrolling** for wide tables
|
|
- **Fixed headers** during scroll
|
|
|
|
### State Management
|
|
- **Persistent filters** using Pinia store (`useFiltersStore`)
|
|
- **Automatic filter initialization** on component mount
|
|
- **Cross-component filter synchronization**
|
|
|
|
## Usage Examples
|
|
|
|
### Basic Table
|
|
```vue
|
|
<script setup>
|
|
const columns = [
|
|
{ fieldName: 'id', label: 'ID', sortable: true },
|
|
{ fieldName: 'name', label: 'Name', sortable: true, filterable: true },
|
|
{ fieldName: 'email', label: 'Email', filterable: true }
|
|
]
|
|
|
|
const data = [
|
|
{ id: 1, name: 'John Doe', email: 'john@example.com' },
|
|
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
|
|
]
|
|
</script>
|
|
|
|
<template>
|
|
<DataTable
|
|
:columns="columns"
|
|
:data="data"
|
|
table-name="users-table"
|
|
/>
|
|
</template>
|
|
```
|
|
|
|
### Status Table
|
|
```vue
|
|
<script setup>
|
|
const columns = [
|
|
{ fieldName: 'task', label: 'Task', sortable: true, filterable: true },
|
|
{ fieldName: 'status', label: 'Status', type: 'status', sortable: true, filterable: true },
|
|
{ fieldName: 'assignee', label: 'Assignee', filterable: true }
|
|
]
|
|
|
|
const data = [
|
|
{ id: 1, task: 'Setup project', status: 'completed', assignee: 'John' },
|
|
{ id: 2, task: 'Write tests', status: 'in progress', assignee: 'Jane' },
|
|
{ id: 3, task: 'Deploy app', status: 'not started', assignee: 'Bob' }
|
|
]
|
|
</script>
|
|
|
|
<template>
|
|
<DataTable
|
|
:columns="columns"
|
|
:data="data"
|
|
table-name="tasks-table"
|
|
/>
|
|
</template>
|
|
```
|
|
|
|
### Interactive Table with Buttons
|
|
```vue
|
|
<script setup>
|
|
const columns = [
|
|
{ fieldName: 'name', label: 'Name', sortable: true, filterable: true },
|
|
{ fieldName: 'status', label: 'Status', type: 'status', sortable: true },
|
|
{ fieldName: 'action', label: 'Action', type: 'button' }
|
|
]
|
|
|
|
const data = [
|
|
{ id: 1, name: 'Project A', status: 'completed', action: 'View Details' },
|
|
{ id: 2, name: 'Project B', status: 'in progress', action: 'Edit' }
|
|
]
|
|
|
|
const handleRowClick = (slotProps) => {
|
|
const { data, index } = slotProps
|
|
console.log(`Action clicked for ${data.name} at row ${index}`)
|
|
// Handle the action (navigate, open modal, etc.)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<DataTable
|
|
:columns="columns"
|
|
:data="data"
|
|
table-name="projects-table"
|
|
@row-click="handleRowClick"
|
|
/>
|
|
</template>
|
|
```
|
|
|
|
### Custom Filters
|
|
```vue
|
|
<script setup>
|
|
import { FilterMatchMode } from '@primevue/core'
|
|
|
|
const customFilters = {
|
|
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
|
name: { value: 'John', matchMode: FilterMatchMode.STARTS_WITH }
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<DataTable
|
|
:columns="columns"
|
|
:data="data"
|
|
:filters="customFilters"
|
|
table-name="filtered-table"
|
|
/>
|
|
</template>
|
|
```
|
|
|
|
## Store Integration
|
|
|
|
The component integrates with a Pinia store (`useFiltersStore`) for persistent filter state:
|
|
|
|
### Store Methods Used
|
|
- `initializeTableFilters(tableName, columns)` - Initialize filters for a table
|
|
- `getTableFilters(tableName)` - Get current filters for a table
|
|
- `updateTableFilter(tableName, fieldName, value, matchMode)` - Update a specific filter
|
|
|
|
### Filter Persistence
|
|
- Filters are automatically saved when changed
|
|
- Filters persist across component re-mounts
|
|
- Each table maintains separate filter state based on `tableName`
|
|
|
|
## Styling
|
|
|
|
The component uses PrimeVue's default DataTable styling with:
|
|
- **Scrollable layout** with fixed 70vh height
|
|
- **Responsive design** that adapts to container width
|
|
- **Consistent spacing** and typography
|
|
- **Accessible color schemes** for status badges
|
|
|
|
## Performance Considerations
|
|
|
|
### Large Datasets
|
|
- **Virtual scrolling** is not implemented - consider for datasets > 1000 rows
|
|
- **Client-side pagination** may impact performance with very large datasets
|
|
- **Debounced filtering** helps with real-time search performance
|
|
|
|
### Memory Management
|
|
- **Filter state persistence** may accumulate over time
|
|
- Consider implementing filter cleanup for unused tables
|
|
- **Component re-rendering** is optimized through computed properties
|
|
|
|
## Best Practices
|
|
|
|
1. **Use unique `tableName`** for each table instance to avoid filter conflicts
|
|
2. **Define clear column labels** for better user experience
|
|
3. **Enable sorting and filtering** on searchable/comparable columns
|
|
4. **Use appropriate column types** (`status`, `button`) for better UX
|
|
5. **Handle `rowClick` events** for interactive functionality
|
|
6. **Consider data structure** - ensure `id` field exists for selection
|
|
7. **Test with various data sizes** to ensure performance
|
|
8. **Use consistent status values** for proper badge coloring
|
|
|
|
## Accessibility
|
|
|
|
The component includes:
|
|
- **Keyboard navigation** support via PrimeVue
|
|
- **Screen reader compatibility** with proper ARIA labels
|
|
- **High contrast** status badges for visibility
|
|
- **Focus management** for interactive elements
|
|
- **Semantic HTML structure** for assistive technologies
|
|
|
|
## Browser Support
|
|
|
|
Compatible with all modern browsers that support:
|
|
- Vue 3 Composition API
|
|
- ES6+ features
|
|
- CSS Grid and Flexbox
|
|
- PrimeVue components
|
|
|
|
## Dependencies
|
|
|
|
- **Vue 3** with Composition API
|
|
- **PrimeVue** DataTable, Column, Tag, Button, InputText components
|
|
- **@primevue/core** for FilterMatchMode
|
|
- **Pinia** store for state management (`useFiltersStore`) |