LinkDesk/frontend/docs/tanstack-table-row-selectio...

4.0 KiB

TanStack Table Row Selection Verification

Comparison with Official Example

This document verifies that our TasksDataTable implementation follows TanStack Table best practices by comparing it with the official row selection example.

Reference: https://github.com/TanStack/table/blob/main/examples/vue/row-selection/src/App.vue

Key Implementation Points

1. Row Selection State Management

Official Example:

const rowSelection = ref<RowSelectionState>({})

const table = useVueTable({
  state: {
    get rowSelection() {
      return rowSelection.value
    },
  },
  onRowSelectionChange: updateOrValue => {
    rowSelection.value =
      typeof updateOrValue === 'function'
        ? updateOrValue(rowSelection.value)
        : updateOrValue
  },
})

Our Implementation:

const rowSelection = ref<RowSelectionState>({})

const table = useVueTable({
  state: {
    get rowSelection() {
      return rowSelection.value
    },
  },
  onRowSelectionChange: (updaterOrValue) => {
    rowSelection.value =
      typeof updaterOrValue === 'function'
        ? updaterOrValue(rowSelection.value)
        : updaterOrValue
  },
})

Status: Identical implementation

2. Enable Row Selection

Official Example:

enableRowSelection: true

Our Implementation:

enableRowSelection: true,
getRowId: (row) => String(row.id),

Status: Correct - We additionally specify getRowId to use task IDs as row identifiers

3. Select All Checkbox

Official Example:

header: ({ table }) => {
  return (
    <IndeterminateCheckbox
      checked={table.getIsAllRowsSelected()}
      indeterminate={table.getIsSomeRowsSelected()}
      onChange={table.getToggleAllRowsSelectedHandler()}
    />
  )
}

Our Implementation:

header: ({ table }) => {
  const isAllSelected = table.getIsAllPageRowsSelected()
  const isSomeSelected = table.getIsSomePageRowsSelected()
  
  return h(Checkbox, {
    checked: isAllSelected ? true : isSomeSelected ? 'indeterminate' : false,
    'onUpdate:checked': (value: boolean | 'indeterminate') => {
      table.toggleAllPageRowsSelected(value === true)
    },
    ariaLabel: 'Select all',
  })
}

Status: Correct - We use getIsAllPageRowsSelected() which is appropriate for our use case (filtered/paginated data)

4. Row Selection Watcher

Our Implementation (Additional Feature):

watch(
  rowSelection,
  (newSelection) => {
    const selectedIds = Object.keys(newSelection)
      .filter(key => newSelection[key])
      .map(key => parseInt(key))
    emit('selection-change', selectedIds)
  },
  { deep: true }
)

Status: This is a custom enhancement to emit selection changes to the parent component

Design Differences (Intentional)

1. Row Checkboxes

Official Example: Shows checkboxes in each row cell Our Implementation: No checkboxes in row cells - selection via row clicks

Reason: Our design uses click-based selection (single click, Ctrl+click, Shift+click) instead of checkboxes in each row. This provides a more streamlined UI and follows common file manager selection patterns.

2. Custom Click Handlers

Our Implementation: Custom click handlers for:

  • Single click: Select only clicked row
  • Ctrl/Cmd+click: Toggle selection
  • Shift+click: Range selection
  • Right-click: Context menu with selection preservation

Status: This is intentional and follows the requirements in the design document

Conclusion

Our TasksDataTable implementation correctly follows TanStack Table best practices for row selection. The differences from the official example are intentional design choices that:

  1. Use click-based selection instead of row checkboxes
  2. Emit selection changes to parent component
  3. Support advanced selection patterns (range, toggle, context menu)
  4. Use getIsAllPageRowsSelected() for filtered data

All TypeScript types are correct, and there are no diagnostic errors.

Verification Date: 2025-11-26 Status: VERIFIED CORRECT