LinkDesk/frontend/docs/shots-datatable-checkbox-fi...

94 lines
3.6 KiB
Markdown

# ShotsDataTable Checkbox Selection Fix
## Issue
The shot table multi-selection wasn't working. Investigation revealed that the actual component being used is `ShotsDataTable.vue` (not `ShotsTableView.vue`), which uses TanStack Table with render functions.
## Root Cause
The checkbox columns in `columns.ts` were using the wrong event binding:
- Used: `'onUpdate:checked'`
- Should use: `'onUpdate:modelValue'` (for v-model binding in render functions)
Additionally, the value parameter type needed to handle both `boolean` and `'indeterminate'` values.
## Fix Applied
### File: `frontend/src/components/shot/columns.ts`
**Before:**
```typescript
header: ({ table }) =>
h(Checkbox, {
checked: table.getIsAllPageRowsSelected(),
indeterminate: table.getIsSomePageRowsSelected(),
'onUpdate:checked': (value: boolean) => table.toggleAllPageRowsSelected(!!value),
ariaLabel: 'Select all',
}),
cell: ({ row }) =>
h(Checkbox, {
checked: row.getIsSelected(),
'onUpdate:checked': (value: boolean) => row.toggleSelected(!!value),
ariaLabel: 'Select row',
onClick: (e: Event) => e.stopPropagation(),
}),
```
**After:**
```typescript
header: ({ table }) =>
h(Checkbox, {
modelValue: table.getIsAllPageRowsSelected(),
'onUpdate:modelValue': (value: boolean | 'indeterminate') => table.toggleAllPageRowsSelected(value === true),
ariaLabel: 'Select all',
}),
cell: ({ row }) =>
h(Checkbox, {
modelValue: row.getIsSelected(),
'onUpdate:modelValue': (value: boolean | 'indeterminate') => row.toggleSelected(value === true),
ariaLabel: 'Select row',
onClick: (e: Event) => e.stopPropagation(),
}),
```
## Key Changes
1. **Event Binding**: Changed from `'onUpdate:checked'` to `'onUpdate:modelValue'`
- When using `h()` render function, v-model binds to `modelValue` prop and `onUpdate:modelValue` event
2. **Prop Binding**: Changed from `checked` to `modelValue`
- Matches the v-model convention for render functions
3. **Type Handling**: Updated value parameter type to `boolean | 'indeterminate'`
- Checkbox component can emit 'indeterminate' state
- Convert to boolean with `value === true` before passing to TanStack Table
4. **Removed Indeterminate Prop**: No longer needed as separate prop
- TanStack Table's `getIsSomePageRowsSelected()` is handled internally
## Why This Works
When using Vue's `h()` render function to create components:
- v-model translates to `modelValue` prop + `onUpdate:modelValue` event
- This is different from template syntax where you can use `v-model` directly
- The Checkbox component from shadcn-vue/reka-ui expects this pattern
## Testing
Test the following scenarios:
1. ✅ Click individual checkboxes to select/deselect shots
2. ✅ Click the header checkbox to select all shots
3. ✅ Click the header checkbox again to deselect all shots
4. ✅ Select some shots, verify header shows indeterminate state
5. ✅ With some selected, click header to select all
6. ✅ Verify row highlighting reflects selection state
7. ✅ Verify TanStack Table's selection state is properly maintained
## Related Files
- `frontend/src/components/shot/columns.ts` - Fixed checkbox column definitions
- `frontend/src/components/shot/ShotsDataTable.vue` - Table component using the columns
- `frontend/src/components/shot/ShotBrowser.vue` - Parent component that uses ShotsDataTable
## Notes
- `ShotsTableView.vue` exists but is NOT currently being used in the application
- The actual table implementation uses TanStack Table via `ShotsDataTable.vue`
- This fix is specific to render function usage with TanStack Table