Added table search

This commit is contained in:
lucast committed 2026-10-06 02:52:56 +02:00
1 parent d9e1cb1c6f
commit 24d4f2e577
1 file changed
+46 -11
+46 -11
View File
@@ -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 filteredData = computed(() => {
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 pageCount = computed(() => const pageCount = computed(() =>
Math.max(1, Math.ceil(props.data.length / pageSize.value)), Math.max(1, Math.ceil(filteredData.value.length / pageSize.value)),
) )
const visibleData = computed(() => { const pagedData = computed(() => {
if (!props.pagination) return props.data 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;