8.8 KiB

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

<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:

{
  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:

{
  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"
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

<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

<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

<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

<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)