Files
oa/documentation/flex-table/v-flex-table-with-slots-documentation.md
2025-05-24 01:49:48 +09:00

194 lines
4.5 KiB
Markdown

---
example_bottom: true
---
### Make VFlexTable yours with slots
The easiest way to create complex tables with `<VFlexTable />` is to uses slots.
This allow to use other components and having great control
inside rows (with `#body-cell` slot) and columns (with `#header-column` slot).
To update data dynamically, use `reactive` props so your interface will know
that data is updated, this is disabled by default to prevent
performance issues.
Check the markup for more details about usage.
<!--code-->
```vue
<script setup lang="ts">
const selectedRowsId = ref<number[]>([])
const editCompanyIndex = ref<number>()
const isAllSelected = computed(
() => flexRowsContacts.length === selectedRowsId.value.length,
)
// this is our data
const data = [
{
id: 0,
company: 'Grubspot',
type: 'New Lead',
industry: 'Software',
status: 'Active',
contacts: [
{
id: 0,
picture: 'https://media.cssninja.io/content/avatars/25.jpg',
initials: 'AC',
color: 'info',
},
// and more contacts ..
],
},
// and more data ...
]
// this is the columns configuration
const columns = {
select: {
label: '',
cellClass: 'is-flex-grow-0',
},
company: {
label: 'Company',
grow: true,
},
type: 'Type',
industry: 'Industry',
status: 'Status',
contacts: {
label: 'Contacts',
align: 'end',
},
}
// the select all checkbox click handler
function toggleSelection() {
if (isAllSelected.value) {
selectedRowsId.value = []
}
else {
selectedRowsId.value = flexRowsContacts.map((_, index) => index)
}
}
// this it the row click handler (enabled with clickable props)
function clickOnRow(row: any) {
if (selectedRowsId.value.includes(row.id)) {
selectedRowsId.value = selectedRowsId.value.filter(i => i !== row.id)
}
else {
selectedRowsId.value = [...selectedRowsId.value, row.id]
}
}
// this is the "Contact me" click handler
function contactUser(row: any) {
alert(`Contacting "${row.company}" ...`)
}
// this is a local directive (it begins with V..., usable with v-focus)
// that is used to force the focus on input when mounted
const VFocus = {
mounted(el: HTMLInputElement) {
el.focus()
},
}
</script>
<template>
<VFlexTable
:data="data"
:columns="columns"
clickable
compact
rounded
@row-click="clickOnRow"
>
<!-- header-column slot -->
<template #header-column="{ column }">
<VCheckbox
v-if="column.key === 'select'"
class="ml-2 mr-3"
:checked="isAllSelected"
name="all_selected"
color="primary"
square
@click="toggleSelection"
/>
</template>
<!-- body-cell slot -->
<template #body-cell="{ row, column, value }">
<!--This is the slot for row.select cells-->
<VCheckbox
v-if="column.key === 'select'"
v-model="selectedRowsId"
:value="row.id"
name="selection"
square
/>
<!--This is the slot for row.company cells-->
<template v-else-if="column.key === 'company'">
<VControl v-if="editCompanyIndex === index">
<VField>
<input
v-model="row[column.key]"
v-focus
type="text"
class="input is-primary-focus"
@blur="editCompanyIndex = undefined"
@keydown.enter="editCompanyIndex = undefined"
>
</VField>
</VControl>
<a
v-else
class="is-overlay m-3 is-flex is-align-items-center is-clickable edit-icon-link"
role="button"
tabindex="0"
@click="editCompanyIndex = index"
@keydown.enter="editCompanyIndex = index"
>
{{ value }}
<VIcon
class="is-inline ml-1"
icon="lucide:edit"
role="img"
aria-label="edit-3"
/>
</a>
</template>
<!--This is the slot for row.status cells-->
<VTag
v-else-if="column.key === 'status'"
rounded
:color="
value === 'Suspended'
? 'orange'
: value === 'New'
? 'info'
: value === 'Active'
? 'primary'
: undefined
"
>
{{ value }}
</VTag>
<!--This is the slot for row.contacts cells-->
<VAction v-if="column.key === 'contacts'" @click.stop="contactUser(row)">
Contact me
</VAction>
<!--The default slot is used then-->
</template>
</VFlexTable>
</template>
```
<!--/code-->