UITable
UITable
A versatile table component that provides advanced features for displaying and managing tabular data, including sorting, filtering, pagination, row selection, and custom cell rendering.
<template> <UITable :data="tableData" :columns="columns" :sortable="true" :selectable="true" :loading="isLoading" :pagination="pagination" @sort="handleSort" @select="handleSelect" > <template #header-cell="{ column }"> <div class="flex items-center space-x-2"> <span>{{ column.label }}</span> <InfoIcon v-if="column.tooltip" class="w-4 h-4 text-gray-400" v-tooltip="column.tooltip" /> </div> </template>
<template #cell-actions="{ row }"> <div class="flex items-center space-x-2"> <UIButton size="sm" @click="editRow(row)" > Edit </UIButton> <UIButton size="sm" variant="error" @click="deleteRow(row)" > Delete </UIButton> </div> </template> </UITable></template>
<script setup lang="ts">interface TableColumn { key: string label: string sortable?: boolean tooltip?: string width?: string | number}
const columns: TableColumn[] = [ { key: 'name', label: 'Name', sortable: true }, { key: 'email', label: 'Email', sortable: true }, { key: 'status', label: 'Status', tooltip: 'Current user status' }, { key: 'actions', label: 'Actions', width: '120px' }]
const tableData = ref([])const isLoading = ref(false)const pagination = reactive({ page: 1, perPage: 10, total: 0})
const handleSort = (column: TableColumn) => { // Handle sorting}
const handleSelect = (selectedRows: any[]) => { console.log('Selected:', selectedRows)}</script>Props
data(array): Table datacolumns(array): Column definitionssortable(boolean): Enable sortingselectable(boolean): Enable row selectionloading(boolean): Show loading statepagination(object): Pagination configrowKey(string): Unique row identifierbordered(boolean): Show bordersstriped(boolean): Striped rowshover(boolean): Row hover effectdense(boolean): Compact layoutstickyHeader(boolean): Fixed headeremptyText(string): No data messageloadingText(string): Loading message
Events
sort: Column sortselect: Row selectionpage-change: Page changedrow-click: Row clickedcell-click: Cell clickedheader-click: Header clicked
Slots
header-cell: Custom header cellcell: Custom cell contentempty: No data stateloading: Loading statepagination: Custom paginationtoolbar: Table toolbar
Usage Examples
- Basic Table:
<template> <UITable :data="users" :columns="columns" /></template>
<script setup>const columns = [ { key: 'name', label: 'Name' }, { key: 'email', label: 'Email' }, { key: 'role', label: 'Role' }]
const users = [ { name: 'John Doe', email: 'john@example.com', role: 'Admin' } // ... more users]</script>- Advanced Table with Custom Cells:
<template> <UITable :data="products" :columns="columns" :sortable="true" :pagination="pagination" class="w-full" > <template #cell-image="{ row }"> <img :src="row.image" class="w-12 h-12 rounded object-cover" /> </template>
<template #cell-price="{ row }"> <div class="font-medium tabular-nums"> {{ formatCurrency(row.price) }} </div> </template>
<template #cell-status="{ row }"> <UIBadge :variant="getStatusVariant(row.status)" > {{ row.status }} </UIBadge> </template>
<template #cell-actions="{ row }"> <div class="flex space-x-2"> <UIButton size="sm" @click="editProduct(row)" > Edit </UIButton>
<UIButton size="sm" variant="error" @click="deleteProduct(row)" > Delete </UIButton> </div> </template> </UITable></template>
<script setup>const columns = [ { key: 'image', label: 'Image', width: '100px' }, { key: 'name', label: 'Product Name', sortable: true }, { key: 'price', label: 'Price', sortable: true }, { key: 'status', label: 'Status', sortable: true }, { key: 'actions', label: 'Actions', width: '150px' }]
const getStatusVariant = (status) => { switch (status) { case 'In Stock': return 'success' case 'Low Stock': return 'warning' case 'Out of Stock': return 'error' default: return 'gray' }}</script>- Selectable Table with Toolbar:
<template> <div class="space-y-4"> <UITable :data="employees" :columns="columns" :selectable="true" :selected="selected" @select="handleSelect" > <template #toolbar> <div class="flex items-center justify-between p-4"> <div class="flex items-center space-x-4"> <UISearch v-model="search" placeholder="Search employees..." @search="handleSearch" />
<UISelect v-model="filters.department" :options="departments" placeholder="Department" class="w-40" /> </div>
<div class="flex items-center space-x-2"> <UIButton v-if="selected.length" variant="error" @click="bulkDelete" > Delete Selected </UIButton>
<UIButton type="primary" @click="addEmployee" > Add Employee </UIButton> </div> </div> </template>
<template #cell-avatar="{ row }"> <div class="flex items-center space-x-3"> <img :src="row.avatar" class="w-8 h-8 rounded-full" /> <div> <div class="font-medium"> {{ row.name }} </div> <div class="text-sm text-gray-500"> {{ row.email }} </div> </div> </div> </template> </UITable>
<UIPagination v-model="pagination.page" :total="pagination.total" :per-page="pagination.perPage" @change="handlePageChange" /> </div></template>
<script setup>const selected = ref([])const search = ref('')const filters = reactive({ department: ''})
const pagination = reactive({ page: 1, perPage: 10, total: 0})
const handleSelect = (rows) => { selected.value = rows}
const handleSearch = async (query) => { // Implement search}
const handlePageChange = async (page) => { pagination.page = page await loadData()}</script>Best Practices
-
Performance:
- Virtual scrolling
- Lazy loading
- Optimized rendering
- Efficient sorting
-
User Experience:
- Clear headers
- Responsive layout
- Loading states
- Error handling
-
Accessibility:
- ARIA labels
- Keyboard navigation
- Screen reader support
- Focus management
-
Data Management:
- Efficient updates
- State persistence
- Error recovery
- Data validation
Common Use Cases
- Data Grid:
<template> <DataGrid :data="gridData" :loading="loading" :error="error" > <template #toolbar> <GridToolbar v-model:filters="filters" @refresh="refreshData" @export="exportData" /> </template>
<UITable :data="filteredData" :columns="columns" :sortable="true" :selectable="true" :loading="loading" > <!-- Custom cell templates --> </UITable>
<template #footer> <GridFooter :pagination="pagination" :selection="selected" @page-change="handlePageChange" /> </template> </DataGrid></template>- CRUD Interface:
<template> <div class="crud-interface"> <CrudToolbar :selected="selected" @create="openCreateModal" @delete="confirmDelete" @refresh="refreshData" />
<UITable :data="items" :columns="columns" :selectable="true" :loading="loading" @select="handleSelect" > <template #cell-actions="{ row }"> <CrudActions :item="row" @edit="openEditModal" @delete="confirmDelete" @view="viewDetails" /> </template> </UITable>
<CrudModal v-model="showModal" :mode="modalMode" :item="selectedItem" @save="handleSave" /> </div></template>- Analytics Dashboard:
<template> <div class="analytics-dashboard"> <DashboardFilters v-model="filters" @apply="applyFilters" />
<div class="grid grid-cols-3 gap-6 mb-6"> <MetricCard v-for="metric in metrics" :key="metric.id" :metric="metric" /> </div>
<UITable :data="analyticsData" :columns="columns" :sortable="true" :loading="loading" > <template #cell-trend="{ row }"> <TrendIndicator :value="row.trend" :change="row.change" /> </template>
<template #cell-chart="{ row }"> <SparklineChart :data="row.chartData" :type="row.chartType" /> </template> </UITable> </div></template>