Skip to content

Instantly share code, notes, and snippets.

@arwinvdv
Created June 24, 2021 07:39
Show Gist options
  • Save arwinvdv/1e35a9b223732bf874b5d4a86f72fc1c to your computer and use it in GitHub Desktop.
Save arwinvdv/1e35a9b223732bf874b5d4a86f72fc1c to your computer and use it in GitHub Desktop.
A very simple vue 3 table
<template>
<div>
<table>
<thead>
<tr>
<th v-for="(column, index) in columns" :key="`col-${index}`" @click="sort(column.field)">{{ column.label }}</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, index_row) in sortedRows" :key="'row' + index_row + uid">
<template v-if="index_row >= max_per_page * (current_page) && index_row < max_per_page * (current_page+1)">
<td v-for="(column, index_col) in columns" :key="`rowcol-${index_row}-${index_col}`">
<template v-if="column.slot === undefined || column.slot === ''">{{ row[column.field] }}</template>
<slot v-else :name="column.slot" :row="row"></slot>
</td>
</template>
</tr>
</tbody>
</table>
<div class="flex text-sm justify-center items-center gap-2 p-2">
<button class="btn btn-secondary" @click="current_page > 0 ? current_page-- : null">&lt;</button>
<span>Page {{ current_page + 1 }} of {{ nrOfPages }}</span>
<button class="btn btn-secondary" @click="current_page < (nrOfPages-1) ? current_page++ : null">&gt;</button>
</div>
</div>
</template>
<script>
export default {
name: 'SimpleTable',
props: {
rows: {
type: Array,
default: [],
required: true
},
columns: {
type: Array,
default: [],
required: true
}
},
data: function () {
return {
current_sort: 'name',
current_sort_dir: 'asc',
current_page: 0,
max_per_page: 50,
uid: '',
}
},
computed: {
nrOfPages() {
return Math.ceil(this.rows.length / this.max_per_page)
},
sortedRows() {
return this.rows.sort((a, b) => {
let modifier = 1
if (this.current_sort_dir === 'desc') modifier = -1
if (a[this.current_sort] < b[this.current_sort]) return -1 * modifier
if (a[this.current_sort] > b[this.current_sort]) return 1 * modifier
return 0
})
}
},
watch: {
sortedRows: {
immediate: true,
handler(newVal, oldVal) {
this.uid = Date.now() // fix for index v-for
}
}
},
methods: {
sort: function (s) {
//if s == current sort reverse
if (s === this.current_sort) {
this.current_sort_dir = this.current_sort_dir === 'asc' ? 'desc' : 'asc'
}
this.current_sort = s
this.uid = Date.now() // Fix for index v-for
},
}
}
</script>
=====================
HOW TO USE:
<template>
<simple-table :columns="columns" :rows="rows">
<template v-slot:name="slotProps">
<a @click="">{{ slotProps.row.name }}</a>
</template>
<template v-slot:action>
<button class="btn btn-success" @click="">Open</button>
</template>
</simple-table>
</template>
<script>
import SimpleTable from '../components/vue-3-simple-table.vue'
export default {
components: {SimpleTable},
data: function () {
return {
columns: [
{
field: 'name',
label: 'Name',
slot: 'name',
},
{
field: 'description',
label: 'Description',
},
{
field: '',
label: 'Action',
slot: 'action',
},
],
rows: [
{
name: 'Row 1',
description: 'Some description',
},
{
name: 'Row 2',
description: 'Some description 2',
}
],
}
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment