Skip to content

Commit

Permalink
feat(data-table): add row slot (#4478)
Browse files Browse the repository at this point in the history
  • Loading branch information
m0ksem authored Feb 17, 2025
1 parent aca3543 commit e54b37f
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 48 deletions.
3 changes: 3 additions & 0 deletions packages/ui/src/components/va-data-table/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# next
- Add `row` slot

# 1.9.3
- Default sorting function now correctly sorts numbers

Expand Down
38 changes: 38 additions & 0 deletions packages/ui/src/components/va-data-table/VaDataTable.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import VaDataTableDemo from './VaDataTable.demo.vue'
import { VaDataTable } from '..'
import { VaPagination } from '../va-pagination'
import { StoryFn } from '@storybook/vue3'
import { defineStory } from '../../../.storybook/types'

export default {
title: 'VaDataTable',
Expand Down Expand Up @@ -313,3 +314,40 @@ export const ExpandableRowFilter = () => ({
</VaDataTable>
`,
})

export const RowSlot = defineStory({
story: () => ({
components: { VaDataTable },
setup () {
const items = [
{ name: 'Aaa', email: 'a', age: 12 },
{ name: 'Bbb', email: 'b', age: 12 },
{ name: 'Ccc', email: 'c', age: 12 },
{ name: 'Ddd', email: 'd', age: 12 },
{ name: 'Eee', email: 'e', age: 12 },
]

const columns = defineVaDataTableColumns([
{ key: 'name' },
{ key: 'email' },
{ key: 'age' },
]) satisfies Columns

return {
items,
columns,
}
},
template: `
<VaDataTable :items="items" :columns="columns">
<template #row="{ rowData }">
<tr>
<td>{{ rowData.name }}</td>
<td>{{ rowData.email }}</td>
<td>{{ rowData.age }}</td>
</tr>
</template>
</VaDataTable>
`,
}),
})
98 changes: 50 additions & 48 deletions packages/ui/src/components/va-data-table/VaDataTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -104,55 +104,57 @@
v-for="(row, index) in renderBuffer"
:key="`table-row_${uniqueKey(row, index)}`"
>
<tr
class="va-data-table__table-tr"
:class="[{ selected: isRowSelected(row), 'va-data-table__table-tr--expanded': row.isExpandableRowVisible }]"
v-bind="getRowBind(row)"
@click="onRowClickHandler('row:click', $event, row)"
@dblclick="onRowClickHandler('row:dblclick', $event, row)"
@contextmenu="onRowClickHandler('row:contextmenu', $event, row)"
>
<td
v-if="selectable && !$props.grid"
class="va-data-table__table-td va-data-table__table-cell-select"
:key="`selectable_${uniqueKey(row, index)}`"
@selectstart.prevent
>
<va-checkbox
class="va-data-table__table-cell-checkbox"
:model-value="isRowSelected(row)"
:color="selectedColor"
:aria-label="tp($props.ariaSelectRowLabel, { index: row.initialIndex })"
@click.shift.exact.stop="shiftSelectRows(row)"
@click.ctrl.exact.stop="ctrlSelectRow(row)"
@click.exact.stop="ctrlSelectRow(row)"
/>
</td>

<td
v-for="(cell, cellIndex) in row.cells"
:key="`table-cell_${cell.column.name + cell.rowIndex}`"
class="va-data-table__table-td"
:class="getClass(cell.column.tdClass)"
:style="[
cell.column.width ? { minWidth: cell.column.width, maxWidth: cell.column.width } : {},
getCellCSSVariables(cell),
getStyle(cell.column.tdStyle),
]"
v-bind="getCellBind(cell, row)"
<slot name="row" v-bind="row">
<tr
class="va-data-table__table-tr"
:class="[{ selected: isRowSelected(row), 'va-data-table__table-tr--expanded': row.isExpandableRowVisible }]"
v-bind="getRowBind(row)"
@click="onRowClickHandler('row:click', $event, row)"
@dblclick="onRowClickHandler('row:dblclick', $event, row)"
@contextmenu="onRowClickHandler('row:contextmenu', $event, row)"
>
<slot
v-if="`cell(${cell.column.name})` in $slots"
:name="`cell(${cell.column.name})`"
v-bind="{ ...cell, row, isExpanded: row.isExpandableRowVisible }"
/>

<slot v-else name="cell" v-bind="{ cell, row }">
<span v-if="$props.grid" class="va-data-table__grid-column-header">{{ columnsComputed[cellIndex].label }}</span>
{{ cellData(cell, columnsComputed[cellIndex]) }}
</slot>
</td>
</tr>
<td
v-if="selectable && !$props.grid"
class="va-data-table__table-td va-data-table__table-cell-select"
:key="`selectable_${uniqueKey(row, index)}`"
@selectstart.prevent
>
<va-checkbox
class="va-data-table__table-cell-checkbox"
:model-value="isRowSelected(row)"
:color="selectedColor"
:aria-label="tp($props.ariaSelectRowLabel, { index: row.initialIndex })"
@click.shift.exact.stop="shiftSelectRows(row)"
@click.ctrl.exact.stop="ctrlSelectRow(row)"
@click.exact.stop="ctrlSelectRow(row)"
/>
</td>

<td
v-for="(cell, cellIndex) in row.cells"
:key="`table-cell_${cell.column.name + cell.rowIndex}`"
class="va-data-table__table-td"
:class="getClass(cell.column.tdClass)"
:style="[
cell.column.width ? { minWidth: cell.column.width, maxWidth: cell.column.width } : {},
getCellCSSVariables(cell),
getStyle(cell.column.tdStyle),
]"
v-bind="getCellBind(cell, row)"
>
<slot
v-if="`cell(${cell.column.name})` in $slots"
:name="`cell(${cell.column.name})`"
v-bind="{ ...cell, row, isExpanded: row.isExpandableRowVisible }"
/>

<slot v-else name="cell" v-bind="{ cell, row }">
<span v-if="$props.grid" class="va-data-table__grid-column-header">{{ columnsComputed[cellIndex].label }}</span>
{{ cellData(cell, columnsComputed[cellIndex]) }}
</slot>
</td>
</tr>
</slot>
<tr v-if="row.isExpandableRowVisible" class="va-data-table__table-tr" :key="`table-expandable-row_${uniqueKey(row, index)}`">
<td
class="va-data-table__table-expanded-content"
Expand Down

0 comments on commit e54b37f

Please sign in to comment.