Added table search
This commit is contained in:
1 parent
d9e1cb1c6f
commit
24d4f2e577
1 file changed
+47
-12
+47
-12
@@ -15,23 +15,47 @@ type TableProps = {
|
|||||||
data: any
|
data: any
|
||||||
pagination?: boolean
|
pagination?: boolean
|
||||||
pageSize?: number
|
pageSize?: number
|
||||||
|
search?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = withDefaults(defineProps<TableProps>(), {
|
const props = withDefaults(defineProps<TableProps>(), {
|
||||||
pagination: false,
|
pagination: false,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
|
search: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
const currentPage = ref(1)
|
const currentPage = ref(1)
|
||||||
|
const query = ref("")
|
||||||
const pageSize = computed(() => Math.max(1, Math.floor(props.pageSize)))
|
const pageSize = computed(() => Math.max(1, Math.floor(props.pageSize)))
|
||||||
const pageCount = computed(() =>
|
const filteredData = computed(() => {
|
||||||
Math.max(1, Math.ceil(props.data.length / pageSize.value)),
|
const normalizedQuery = query.value.trim().toLocaleLowerCase()
|
||||||
|
const indexedData = props.data.map((item: any, index: number) => ({
|
||||||
|
item,
|
||||||
|
index,
|
||||||
|
}))
|
||||||
|
|
||||||
|
if (!props.search || !normalizedQuery) return indexedData
|
||||||
|
|
||||||
|
return indexedData.filter(({ item }: { item: any }) =>
|
||||||
|
props.rows.some((row) =>
|
||||||
|
String(item[row.name] ?? "")
|
||||||
|
.toLocaleLowerCase()
|
||||||
|
.includes(normalizedQuery),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
const visibleData = computed(() => {
|
})
|
||||||
if (!props.pagination) return props.data
|
const pageCount = computed(() =>
|
||||||
|
Math.max(1, Math.ceil(filteredData.value.length / pageSize.value)),
|
||||||
|
)
|
||||||
|
const pagedData = computed(() => {
|
||||||
|
if (!props.pagination) return filteredData.value
|
||||||
|
|
||||||
const start = (currentPage.value - 1) * pageSize.value
|
const start = (currentPage.value - 1) * pageSize.value
|
||||||
return props.data.slice(start, start + pageSize.value)
|
return filteredData.value.slice(start, start + pageSize.value)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(query, () => {
|
||||||
|
currentPage.value = 1
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(pageCount, (count) => {
|
watch(pageCount, (count) => {
|
||||||
@@ -40,6 +64,13 @@ watch(pageCount, (count) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<Input
|
||||||
|
v-if="props.search"
|
||||||
|
v-model:value="query"
|
||||||
|
type="search"
|
||||||
|
placeholder="Search table"
|
||||||
|
class="table-search"
|
||||||
|
/>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -55,25 +86,25 @@ watch(pageCount, (count) => {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr
|
<tr
|
||||||
v-for="(item, i) in visibleData"
|
v-for="entry in pagedData"
|
||||||
:key="(currentPage - 1) * pageSize + i"
|
:key="entry.index"
|
||||||
>
|
>
|
||||||
<td v-for="(row, j) in props.rows" :key="j">
|
<td v-for="(row, j) in props.rows" :key="j">
|
||||||
<slot
|
<slot
|
||||||
:name="row.name"
|
:name="row.name"
|
||||||
:item="item"
|
:item="entry.item"
|
||||||
:index="props.pagination ? (currentPage - 1) * pageSize + i : i"
|
:index="entry.index"
|
||||||
>
|
>
|
||||||
<nuxt-img
|
<nuxt-img
|
||||||
v-if="row.type == 'image'"
|
v-if="row.type == 'image'"
|
||||||
:src="GET_FILE(item[row.name])"
|
:src="GET_FILE(entry.item[row.name])"
|
||||||
/>
|
/>
|
||||||
<audio
|
<audio
|
||||||
v-else-if="row.type == 'audio'"
|
v-else-if="row.type == 'audio'"
|
||||||
controls
|
controls
|
||||||
:src="GET_AUDIO_FILE(item[row.name])"
|
:src="GET_AUDIO_FILE(entry.item[row.name])"
|
||||||
/>
|
/>
|
||||||
<p v-else>{{ item[row.name] }}</p>
|
<p v-else>{{ entry.item[row.name] }}</p>
|
||||||
</slot>
|
</slot>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -148,6 +179,10 @@ watch(pageCount, (count) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.table-search {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|||||||
Reference in new issue
Block a user