This content originally appeared on DEV Community and was authored by dtechmaster
I just wan't to be sure if this is the right way to name and use slots dynamicaly. I'm not having any problem with this, the problem is that despite it works, I can't find anyone or any docs doing this so I decided publish a post here so you guys can judge this code and point eventual problems that I'm not seeing.
My environment
Nuxt 3
d-virtual-table Component
description: The component purpose is a table with slots that I can use named dynamically based on my input values so I can replace default components by a column.field or a column.type based on the need when creating a page/screen.
<template>
<RecycleScroller class="scroller" :items="rows" :item-size="63" key-field="name" listTag="table"
listClass="data-table" itemTag="tr" itemClass="" :buffer="200">
<template #before="{ item: row }">
<table class="data-table">
<thead>
<tr class="data-table-header">
<th v-for="column in columns">
<slot :name="`column-${column.field}`" :row="row" :column="column" :value="column.field"
>
<slot :name="`column-${column.type}`" :row="row" :column="column" :value="column.field"
>
{{ column.field }} ({{ column.type }})
</slot>
</slot>
</th>
</tr>
</thead>
</table>
</template>
<template #default="{ item: row, index }">
<td v-for="col in columns" :class="getOddEven(index)">
<slot :name="col.field" :row="row" :column="col" :value="row[col.field]" :index="index">
<slot :name="col.type" :row="row" :column="col" :value="row[col.field]" :index="index">
{{ row[col.field] }}
</slot>
</slot>
</td>
</template>
</RecycleScroller>
</template>
<script setup lang="ts">
interface Column {
label: string
field: string
type?: string
dateOutputFormat?: string
dateInputFormat?: string
}
interface Row {
id: number
name: string
age: number
createdAt: string
score: number
}
defineProps<{
columns: Column[]
rows: Row[]
}>()
function getOddEven(index: number) {
if (typeof index !== 'number') {
return '';
}
return index % 2 === 0 ? 'row-even' : 'row-odd';
}
</script>
<style>
.scroller {
height: 100%;
}
.user {
height: 32%;
padding: 0 12px;
display: flex;
align-items: center;
}
.data-table {
border-collapse: collapse !important;
width: 100%;
}
.data-table tr {
width: 100%;
display: flex;
}
.data-table td,
.data-table th {
padding: 10px 15px;
border: 1px solid black;
flex: 1;
}
.data-table-header th {
font-weight: 700;
padding: 10px 15px;
border: 1px solid black;
}
.row-odd {
background-color: white;
}
.row-even {
background-color: rgba(210, 210, 210, 0.507);
}
tbody {
display: block;
}
</style>
Component usage
<template>
<div class="page-wrapper">
<!-- <d-virtual-table :rows="rows" :columns="columns" /> -->
<d-virtual-table :rows="rows" :columns="columns">
<template #column-name="{row, column, value}">
{{ value }} (ABC)
</template>
<template #column-age="{row, column, value}">
{{ value }} (N)
</template>
<template #column-date="{row, column, value}">
{{ value }} yy/mm/dd
</template>
<template #column-score="{row, column, value}">
{{ value }} (%)
</template>
<template #string="{row,column,value}">
<v-text-field density="compact" variant="outlined" hide-details type="text" :label="column.label" v-model="row[column.field]" />
</template>
<template #score="{row,column,value}">
<v-chip class="border" type="text" v-model="row[column.field]" :text="value"/> %
</template>
</d-virtual-table>
</div>
</template>
<script setup lang="ts">
const columns = [
{
label: 'Name',
field: 'name',
type: 'string'
},
{
label: 'Age',
field: 'age',
type: 'number',
},
{
label: 'Created On',
field: 'createdAt',
type: 'date',
dateInputFormat: 'yyyy-MM-dd',
dateOutputFormat: 'MMM do yy',
},
{
label: 'Percent',
field: 'score',
type: 'string',
},
];
const rows = [
{ id: 1, name: "John", age: 20, createdAt: '', score: 0.03343 },
{ id: 2, name: "Jane", age: 24, createdAt: '2011-10-31', score: 0.03343 },
{ id: 3, name: "Susan", age: 16, createdAt: '2011-10-30', score: 0.03343 },
{ id: 4, name: "Chris", age: 55, createdAt: '2011-10-11', score: 0.03343 },
{ id: 5, name: "Dan", age: 40, createdAt: '2011-10-21', score: 0.03343 },
{ id: 6, name: "John", age: 20, createdAt: '2011-10-31', score: 0.03343 },
];
</script>
<style scoped>
.page-wrapper {
height: 100dvh;
max-height: 100dvh;
overflow: hidden;
}
</style>
The only thing I found about this is the bellow vue 3 docs which seems wrong or incomplete? looks like just the usage part is here or am I just not getting this?
https://vuejs.org/guide/components/slots.html#dynamic-slot-names
Well, that's it. anything wrong with this? Thank very much for you guys time.
This content originally appeared on DEV Community and was authored by dtechmaster
dtechmaster | Sciencx (2024-09-24T06:44:12+00:00) Dynamic Slot Names Usage. Retrieved from https://www.scien.cx/2024/09/24/dynamic-slot-names-usage/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.