Skip to content

Table ​

Компонент таблицы, управляемый данными. Передавайте columns и data как JSON, настраивайте ячейки через scoped-слоты.

Basic ​

NameEmailRoleStatusJoined
OMOlivia Martin
olivia.martin@email.comAdmin ActiveJan 4, 2024
JLJackson Lee
jackson.lee@email.comEditor ActiveFeb 12, 2024
INIsabella Nguyen
isabella.nguyen@email.comViewer InactiveMar 8, 2024
WKWilliam Kim
will@email.comEditor ActiveApr 22, 2024
SDSofia Davis
sofia.davis@email.comAdmin PendingMay 15, 2024
LJLiam Johnson
liam.j@email.comViewer BannedJun 1, 2024
vue
<script setup>
import { VxTable } from 'veloxui'

// Define table columns — each column needs a unique "key" matching a field in the data
const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
  { key: 'joined', label: 'Joined' },
]

// Row data — each object should have keys matching the column "key" values
const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active', joined: 'Jan 4, 2024' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active', joined: 'Feb 12, 2024' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive', joined: 'Mar 8, 2024' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active', joined: 'Apr 22, 2024' },
  { name: 'Sofia Davis', email: 'sofia.davis@email.com', role: 'Admin', status: 'Pending', joined: 'May 15, 2024' },
]
</script>

<template>
  <!-- The simplest usage: just pass columns and data -->
  <VxTable :columns="columns" :data="data" />

  <!-- You can customize any cell using a slot named after the column key -->
  <VxTable :columns="columns" :data="data">
    <!-- Slot props: row = full row object, value = cell value, index = row index -->
    <template #name="{ row }">
      <strong>{{ row.name }}</strong>
    </template>
    <template #email="{ value }">
      <span style="font-family: monospace; font-size: 13px;">{{ value }}</span>
    </template>
    <template #status="{ value }">
      <span :style="{ color: value === 'Active' ? '#22c55e' : '#a1a1aa' }">
        {{ value }}
      </span>
    </template>
  </VxTable>
</template>

Render Function ​

Используйте свойство render у столбца, чтобы напрямую возвращать HTML — слоты не нужны. Отлично подходит для быстрого форматирования без шаблонного кода.

NameEmailRoleStatusJoined
OM Olivia Martin
olivia.martin@email.comAdmin Active Jan 4, 2024
JL Jackson Lee
jackson.lee@email.comEditor Active Feb 12, 2024
IN Isabella Nguyen
isabella.nguyen@email.comViewer Inactive Mar 8, 2024
WK William Kim
will@email.comEditor Active Apr 22, 2024
SD Sofia Davis
sofia.davis@email.comAdmin Pending May 15, 2024
LJ Liam Johnson
liam.j@email.comViewer Banned Jun 1, 2024
vue
<script setup>
import { VxTable } from 'veloxui'

// The "render" property returns an HTML string — no slot needed
const columns = [
  {
    key: 'name',
    label: 'Name',
    render: (row) => `<strong>${row.name}</strong>`,
  },
  {
    key: 'status',
    label: 'Status',
    render: (row) => {
      const colors = { Active: '#22c55e', Inactive: '#a1a1aa', Pending: '#f59e0b' }
      const color = colors[row.status] || '#a1a1aa'
      return `<span style="color:${color}">${row.status}</span>`
    },
  },
  { key: 'email', label: 'Email' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', status: 'Inactive' },
  { name: 'William Kim', email: 'will@email.com', status: 'Pending' },
]
</script>

<template>
  <VxTable :columns="columns" :data="data" bordered />
</template>

Bordered ​

Добавьте проп bordered для внешней границы, скруглённых углов и разделителей столбцов.

NameEmailRoleStatusJoined
OMOlivia Martin
olivia.martin@email.comAdmin ActiveJan 4, 2024
JLJackson Lee
jackson.lee@email.comEditor ActiveFeb 12, 2024
INIsabella Nguyen
isabella.nguyen@email.comViewer InactiveMar 8, 2024
WKWilliam Kim
will@email.comEditor ActiveApr 22, 2024
SDSofia Davis
sofia.davis@email.comAdmin PendingMay 15, 2024
LJLiam Johnson
liam.j@email.comViewer BannedJun 1, 2024
vue
<script setup>
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
]
</script>

<template>
  <!-- "bordered" adds outer border, rounded corners, and column dividers -->
  <VxTable :columns="columns" :data="data" bordered />
</template>

Striped ​

Чередующиеся фоны строк с помощью пропа striped.

NameEmailRoleStatusJoined
OMOlivia Martin
olivia.martin@email.comAdmin ActiveJan 4, 2024
JLJackson Lee
jackson.lee@email.comEditor ActiveFeb 12, 2024
INIsabella Nguyen
isabella.nguyen@email.comViewer InactiveMar 8, 2024
WKWilliam Kim
will@email.comEditor ActiveApr 22, 2024
SDSofia Davis
sofia.davis@email.comAdmin PendingMay 15, 2024
LJLiam Johnson
liam.j@email.comViewer BannedJun 1, 2024
vue
<script setup>
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active' },
  { name: 'Sofia Davis', email: 'sofia.davis@email.com', role: 'Admin', status: 'Pending' },
]
</script>

<template>
  <!-- "striped" alternates row background colors for readability -->
  <VxTable :columns="columns" :data="data" striped bordered />
</template>

Fixed Header ​

Установите max-height, чтобы тело таблицы прокручивалось, а шапка автоматически оставалась зафиксированной.

NameEmailRoleStatusJoined
OMOlivia Martin
olivia.martin@email.comAdmin ActiveJan 4, 2024
JLJackson Lee
jackson.lee@email.comEditor ActiveFeb 12, 2024
INIsabella Nguyen
isabella.nguyen@email.comViewer InactiveMar 8, 2024
WKWilliam Kim
will@email.comEditor ActiveApr 22, 2024
SDSofia Davis
sofia.davis@email.comAdmin PendingMay 15, 2024
LJLiam Johnson
liam.j@email.comViewer BannedJun 1, 2024
EWEmma Wilson
emma.wilson@email.comEditor ActiveJul 10, 2024
NBNoah Brown
noah.brown@email.comViewer InactiveAug 3, 2024
AGAva Garcia
ava.garcia@email.comAdmin ActiveSep 18, 2024
EMEthan Miller
ethan.m@email.comEditor PendingOct 5, 2024
MAMia Anderson
mia.anderson@email.comViewer ActiveNov 22, 2024
LTLucas Taylor
lucas.t@email.comAdmin ActiveDec 14, 2024
CTCharlotte Thomas
charlotte.t@email.comEditor BannedJan 8, 2025
JMJames Moore
james.moore@email.comViewer ActiveFeb 19, 2025
vue
<script setup>
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
]

// When there are many rows, use max-height to make the body scrollable
const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active' },
  { name: 'Sofia Davis', email: 'sofia.davis@email.com', role: 'Admin', status: 'Pending' },
  { name: 'Emma Wilson', email: 'emma.wilson@email.com', role: 'Editor', status: 'Active' },
  { name: 'Noah Brown', email: 'noah.brown@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'Ava Garcia', email: 'ava.garcia@email.com', role: 'Admin', status: 'Active' },
  { name: 'Ethan Miller', email: 'ethan.m@email.com', role: 'Editor', status: 'Pending' },
  { name: 'Mia Anderson', email: 'mia.anderson@email.com', role: 'Viewer', status: 'Active' },
  { name: 'Lucas Taylor', email: 'lucas.t@email.com', role: 'Admin', status: 'Active' },
  { name: 'Charlotte Thomas', email: 'charlotte.t@email.com', role: 'Editor', status: 'Inactive' },
]
</script>

<template>
  <!-- max-height keeps the header fixed while the body scrolls -->
  <VxTable :columns="columns" :data="data" :max-height="400" bordered />
</template>

Fixed Columns ​

Установите fixed: 'left' или fixed: 'right' у столбца, чтобы закрепить его, пока остальные прокручиваются горизонтально. Для закреплённых столбцов требуется width.

NameEmailRoleDepartmentLocationStatusJoined
OMOlivia Martin
olivia.martin@email.comAdminEngineeringSan Francisco ActiveJan 4, 2024
JLJackson Lee
jackson.lee@email.comEditorMarketingNew York ActiveFeb 12, 2024
INIsabella Nguyen
isabella.nguyen@email.comViewerDesignLondon InactiveMar 8, 2024
WKWilliam Kim
will@email.comEditorEngineeringTokyo ActiveApr 22, 2024
SDSofia Davis
sofia.davis@email.comAdminProductBerlin PendingMay 15, 2024
EWEmma Wilson
emma.wilson@email.comEditorEngineeringToronto ActiveJun 1, 2024
NBNoah Brown
noah.brown@email.comViewerMarketingSydney InactiveJul 10, 2024
AGAva Garcia
ava.garcia@email.comAdminDesignParis ActiveAug 3, 2024
EMEthan Miller
ethan.m@email.comEditorProductSeoul BannedSep 18, 2024
vue
<script setup>
import { VxTable } from 'veloxui'

// Use "fixed" to pin columns. Requires "width" on fixed columns.
const columns = [
  { key: 'name', label: 'Name', fixed: 'left', width: 180 },
  { key: 'email', label: 'Email', width: 250 },
  { key: 'role', label: 'Role', width: 150 },
  { key: 'department', label: 'Department', width: 180 },
  { key: 'location', label: 'Location', width: 180 },
  { key: 'status', label: 'Status', width: 150 },
  { key: 'joined', label: 'Joined', width: 150 },
  { key: 'actions', label: '', fixed: 'right', width: 80 },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', department: 'Engineering', location: 'San Francisco', status: 'Active', joined: 'Jan 4, 2024' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', department: 'Marketing', location: 'New York', status: 'Active', joined: 'Feb 12, 2024' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', department: 'Design', location: 'London', status: 'Inactive', joined: 'Mar 8, 2024' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', department: 'Engineering', location: 'Tokyo', status: 'Active', joined: 'Apr 22, 2024' },
]
</script>

<template>
  <!-- "Name" stays pinned on the left, "actions" on the right, rest scrolls -->
  <VxTable :columns="columns" :data="data" bordered :max-height="350">
    <template #actions>
      <button style="background: none; border: none; cursor: pointer;">···</button>
    </template>
  </VxTable>
</template>

Selection ​

Добавьте selectable, чтобы показать чекбоксы. Используйте v-model:selected для связывания выбранных значений. По умолчанию используется поле id — установите selection-key, чтобы изменить его.

Выбрано: ничего
NameEmailRoleStatusJoined
OMOlivia Martin
olivia.martin@email.comAdmin ActiveJan 4, 2024
JLJackson Lee
jackson.lee@email.comEditor ActiveFeb 12, 2024
INIsabella Nguyen
isabella.nguyen@email.comViewer InactiveMar 8, 2024
WKWilliam Kim
will@email.comEditor ActiveApr 22, 2024
SDSofia Davis
sofia.davis@email.comAdmin PendingMay 15, 2024
LJLiam Johnson
liam.j@email.comViewer BannedJun 1, 2024
vue
<script setup>
import { ref } from 'vue'
import { VxTable } from 'veloxui'

const selected = ref([])

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor' },
]
</script>

<template>
  <!-- Show which rows are selected -->
  <p>Selected: {{ selected.length ? selected.join(', ') : 'none' }}</p>

  <!-- "selectable" adds checkboxes, "selection-key" sets which field is used as the value -->
  <VxTable
    :columns="columns"
    :data="data"
    selectable
    v-model:selected="selected"
    selection-key="name"
    bordered
  />
  <!-- selected = ['Olivia Martin', 'Jackson Lee'] when those rows are checked -->
</template>

Drag & Drop ​

Добавьте draggable, чтобы включить переупорядочивание строк. Используйте v-model:data для получения обновлённого порядка.

NameEmailRoleStatus
OMOlivia Martin
olivia.martin@email.comAdmin Active
JLJackson Lee
jackson.lee@email.comEditor Active
INIsabella Nguyen
isabella.nguyen@email.comViewer Inactive
WKWilliam Kim
will@email.comEditor Active
SDSofia Davis
sofia.davis@email.comAdmin Pending
LJLiam Johnson
liam.j@email.comViewer Banned
vue
<script setup>
import { ref } from 'vue'
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
]

// Data must be a ref so the table can update the order after drag
const data = ref([
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active' },
  { name: 'Sofia Davis', email: 'sofia.davis@email.com', role: 'Admin', status: 'Pending' },
])
</script>

<template>
  <!-- "draggable" enables row reordering by drag & drop -->
  <!-- v-model:data syncs the new order back to your data ref -->
  <VxTable :columns="columns" v-model:data="data" draggable bordered />
</template>

Resizable Columns ​

Добавьте проп resizable, чтобы пользователи могли перетаскивать границы столбцов для изменения их размера. Также можно установить resizable для каждого столбца в его определении.

NameEmailRoleStatusJoined
OMOlivia Martin
olivia.martin@email.comAdmin ActiveJan 4, 2024
JLJackson Lee
jackson.lee@email.comEditor ActiveFeb 12, 2024
INIsabella Nguyen
isabella.nguyen@email.comViewer InactiveMar 8, 2024
WKWilliam Kim
will@email.comEditor ActiveApr 22, 2024
SDSofia Davis
sofia.davis@email.comAdmin PendingMay 15, 2024
LJLiam Johnson
liam.j@email.comViewer BannedJun 1, 2024
vue
<script setup>
import { VxTable } from 'veloxui'

// Set "width" on columns to define initial widths for resizing
const columns = [
  { key: 'name', label: 'Name', width: 200 },
  { key: 'email', label: 'Email', width: 260 },
  { key: 'role', label: 'Role', width: 140 },
  { key: 'status', label: 'Status', width: 140 },
  { key: 'joined', label: 'Joined', width: 160 },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active', joined: 'Jan 4, 2024' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active', joined: 'Feb 12, 2024' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive', joined: 'Mar 8, 2024' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active', joined: 'Apr 22, 2024' },
]
</script>

<template>
  <!-- Object form: set min/max width limits for all columns -->
  <VxTable :columns="columns" :data="data" :resizable="{ minWidth: 80, maxWidth: 500 }" bordered />

  <!-- Boolean form: enable resizing with default limits (minWidth: 50) -->
  <VxTable :columns="columns" :data="data" resizable bordered />
</template>

Sorting ​

Добавьте sortable, чтобы сделать заголовки столбцов кликабельными. Клик циклически переключает по возрастанию, по убыванию и без сортировки. Используйте v-model:sort для управляемой сортировки или позвольте таблице управлять ею внутренне.

NameEmailRoleStatusJoined
Olivia Martinolivia.martin@email.comAdminActiveJan 4, 2024
Jackson Leejackson.lee@email.comEditorActiveFeb 12, 2024
Isabella Nguyenisabella.nguyen@email.comViewerInactiveMar 8, 2024
William Kimwill@email.comEditorActiveApr 22, 2024
Sofia Davissofia.davis@email.comAdminPendingMay 15, 2024
Liam Johnsonliam.j@email.comViewerBannedJun 1, 2024
vue
<script setup>
import { ref } from 'vue'
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active' },
]

// Optional: control sort state externally
const sort = ref({ key: 'name', order: 'asc' })
</script>

<template>
  <!-- "sortable" makes all column headers clickable to sort -->
  <VxTable :columns="columns" :data="data" sortable bordered />

  <!-- Controlled: bind sort state with v-model:sort -->
  <VxTable :columns="columns" :data="data" sortable v-model:sort="sort" bordered />

  <!-- Per-column: only make specific columns sortable -->
  <VxTable
    :columns="[
      { key: 'name', label: 'Name', sortable: true },
      { key: 'email', label: 'Email' },
    ]"
    :data="data"
    bordered
  />
</template>

Loading ​

Добавьте проп loading, чтобы показать оверлей со спиннером.

NameEmailRoleStatusJoined
Olivia Martinolivia.martin@email.comAdminActiveJan 4, 2024
Jackson Leejackson.lee@email.comEditorActiveFeb 12, 2024
Isabella Nguyenisabella.nguyen@email.comViewerInactiveMar 8, 2024
William Kimwill@email.comEditorActiveApr 22, 2024
Sofia Davissofia.davis@email.comAdminPendingMay 15, 2024
Liam Johnsonliam.j@email.comViewerBannedJun 1, 2024
vue
<script setup>
import { ref } from 'vue'
import { VxTable, VxButton } from 'veloxui'

const loading = ref(false)

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor' },
]

// Simulate a loading state
function toggleLoading() {
  loading.value = true
  setTimeout(() => { loading.value = false }, 2000)
}
</script>

<template>
  <VxButton size="sm" variant="outline" @click="toggleLoading">Toggle loading</VxButton>

  <!-- "loading" shows a spinner overlay on top of the table -->
  <VxTable :columns="columns" :data="data" :loading="loading" bordered />
</template>

Expandable Rows ​

Добавьте expandable, чтобы показать переключатель развёртывания на каждой строке. Предоставьте слот expand для содержимого деталей. Использует selection-key (по умолчанию id) для отслеживания развёрнутых строк.

NameEmailRoleStatusJoined
Olivia Martinolivia.martin@email.comAdminActiveJan 4, 2024
Jackson Leejackson.lee@email.comEditorActiveFeb 12, 2024
Isabella Nguyenisabella.nguyen@email.comViewerInactiveMar 8, 2024
William Kimwill@email.comEditorActiveApr 22, 2024
Sofia Davissofia.davis@email.comAdminPendingMay 15, 2024
Liam Johnsonliam.j@email.comViewerBannedJun 1, 2024
vue
<script setup>
import { ref } from 'vue'
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', joined: 'Jan 4, 2024' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', joined: 'Feb 12, 2024' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', joined: 'Mar 8, 2024' },
]

// Optional: track which rows are expanded externally
const expanded = ref([])
</script>

<template>
  <!-- "expandable" adds an expand toggle to each row -->
  <!-- "selection-key" determines which field uniquely identifies each row -->
  <VxTable :columns="columns" :data="data" expandable selection-key="name" bordered>
    <!-- The "expand" slot renders content below the row when expanded -->
    <template #expand="{ row }">
      <div>
        <strong>{{ row.name }}</strong> joined on {{ row.joined }} as {{ row.role }}.
        <br />Contact: {{ row.email }}
      </div>
    </template>
  </VxTable>

  <!-- Controlled: track expanded rows with v-model:expanded -->
  <VxTable
    :columns="columns"
    :data="data"
    expandable
    v-model:expanded="expanded"
    selection-key="name"
    bordered
  >
    <template #expand="{ row }">
      <div>Details for {{ row.name }}</div>
    </template>
  </VxTable>
</template>

Pagination ​

Добавьте pagination, чтобы показать элементы управления страницами. Передайте true для встроенного состояния или объект для управляемой пагинации.

NameEmailRoleStatusJoined
Olivia Martinolivia.martin@email.comAdminActiveJan 4, 2024
Jackson Leejackson.lee@email.comEditorActiveFeb 12, 2024
Isabella Nguyenisabella.nguyen@email.comViewerInactiveMar 8, 2024
William Kimwill@email.comEditorActiveApr 22, 2024
Sofia Davissofia.davis@email.comAdminPendingMay 15, 2024
Liam Johnsonliam.j@email.comViewerBannedJun 1, 2024
Emma Wilsonemma.wilson@email.comEditorActiveJul 10, 2024
Noah Brownnoah.brown@email.comViewerInactiveAug 3, 2024
Ava Garciaava.garcia@email.comAdminActiveSep 18, 2024
Ethan Millerethan.m@email.comEditorPendingOct 5, 2024
10 / page
1–10 of 14
1 / 2
vue
<script setup>
import { ref } from 'vue'
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active' },
  { name: 'Sofia Davis', email: 'sofia.davis@email.com', role: 'Admin', status: 'Pending' },
  { name: 'Emma Wilson', email: 'emma.wilson@email.com', role: 'Editor', status: 'Active' },
  { name: 'Noah Brown', email: 'noah.brown@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'Ava Garcia', email: 'ava.garcia@email.com', role: 'Admin', status: 'Active' },
]

// Optional: control pagination state (page, pageSize, available sizes)
const page = ref({ page: 1, pageSize: 5, pageSizes: [5, 10, 25] })
</script>

<template>
  <!-- "pagination" as boolean: uses built-in state, defaults to 10 per page -->
  <VxTable :columns="columns" :data="data" pagination bordered />

  <!-- Controlled: bind pagination state with v-model:pagination -->
  <VxTable :columns="columns" :data="data" v-model:pagination="page" bordered />
</template>

Global Filter ​

Передайте строку filter, чтобы искать по всем видимым столбцам.

NameEmailRoleStatusJoined
Olivia Martinolivia.martin@email.comAdminActiveJan 4, 2024
Jackson Leejackson.lee@email.comEditorActiveFeb 12, 2024
Isabella Nguyenisabella.nguyen@email.comViewerInactiveMar 8, 2024
William Kimwill@email.comEditorActiveApr 22, 2024
Sofia Davissofia.davis@email.comAdminPendingMay 15, 2024
Liam Johnsonliam.j@email.comViewerBannedJun 1, 2024
vue
<script setup>
import { ref } from 'vue'
import { VxTable, VxInput } from 'veloxui'

const filterText = ref('')

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active' },
]
</script>

<template>
  <!-- Use VxInput to capture the search text -->
  <VxInput v-model="filterText" placeholder="Search..." size="sm" style="max-width: 260px;" />

  <!-- "filter" searches across all visible columns and hides non-matching rows -->
  <VxTable :columns="columns" :data="data" :filter="filterText" bordered />
</template>

Row Grouping ​

Установите group-by в ключ столбца, чтобы сгруппировать строки со сворачиваемыми заголовками.

NameEmailRoleStatusJoined
Admin(2)
Olivia Martinolivia.martin@email.comAdminActiveJan 4, 2024
Sofia Davissofia.davis@email.comAdminPendingMay 15, 2024
Editor(2)
Jackson Leejackson.lee@email.comEditorActiveFeb 12, 2024
William Kimwill@email.comEditorActiveApr 22, 2024
Viewer(2)
Isabella Nguyenisabella.nguyen@email.comViewerInactiveMar 8, 2024
Liam Johnsonliam.j@email.comViewerBannedJun 1, 2024
vue
<script setup>
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
  { name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active' },
  { name: 'Sofia Davis', email: 'sofia.davis@email.com', role: 'Admin', status: 'Pending' },
]
</script>

<template>
  <!-- "group-by" groups rows by the value of the specified column key -->
  <!-- Rows with the same "role" will be grouped under collapsible headers -->
  <VxTable :columns="columns" :data="data" group-by="role" bordered />
</template>

Column Visibility ​

Добавьте проп column-toggle, чтобы показать встроенный выпадающий список видимости столбцов. Список автоматически заполняется из определения columns с использованием мультиселекта.

Name +4
NameEmailRoleStatusJoined
Olivia Martinolivia.martin@email.comAdminActiveJan 4, 2024
Jackson Leejackson.lee@email.comEditorActiveFeb 12, 2024
Isabella Nguyenisabella.nguyen@email.comViewerInactiveMar 8, 2024
William Kimwill@email.comEditorActiveApr 22, 2024
Sofia Davissofia.davis@email.comAdminPendingMay 15, 2024
Liam Johnsonliam.j@email.comViewerBannedJun 1, 2024
vue
<script setup>
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
  { key: 'joined', label: 'Joined' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active', joined: 'Jan 4, 2024' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active', joined: 'Feb 12, 2024' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive', joined: 'Mar 8, 2024' },
]
</script>

<template>
  <!-- "column-toggle" adds a dropdown to show/hide columns -->
  <VxTable :columns="columns" :data="data" column-toggle bordered />
</template>

Column Reorder ​

Передайте v-model:column-order, чтобы включить переупорядочивание столбцов перетаскиванием.

Перетаскивайте заголовки столбцов для переупорядочивания
NameEmailRoleStatusJoined
Olivia Martinolivia.martin@email.comAdminActiveJan 4, 2024
Jackson Leejackson.lee@email.comEditorActiveFeb 12, 2024
Isabella Nguyenisabella.nguyen@email.comViewerInactiveMar 8, 2024
William Kimwill@email.comEditorActiveApr 22, 2024
Sofia Davissofia.davis@email.comAdminPendingMay 15, 2024
Liam Johnsonliam.j@email.comViewerBannedJun 1, 2024
vue
<script setup>
import { ref } from 'vue'
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
  { key: 'status', label: 'Status' },
  { key: 'joined', label: 'Joined' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active', joined: 'Jan 4, 2024' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active', joined: 'Feb 12, 2024' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive', joined: 'Mar 8, 2024' },
]

// Column order as an array of column keys — drag headers to reorder
const order = ref(['name', 'email', 'role', 'status', 'joined'])
</script>

<template>
  <!-- v-model:column-order enables drag-and-drop column reordering -->
  <VxTable :columns="columns" :data="data" v-model:column-order="order" bordered />
</template>

Inline Editing ​

Установите editable: true у столбца, чтобы включить редактирование по двойному клику. Слушайте @cell-edit, чтобы обновлять данные.

Дважды щёлкните по ячейке Name или Role, чтобы отредактировать
NameEmailRoleStatus
Olivia Martinolivia.martin@email.comAdminActive
Jackson Leejackson.lee@email.comEditorActive
Isabella Nguyenisabella.nguyen@email.comViewerInactive
William Kimwill@email.comEditorActive
vue
<script setup>
import { ref } from 'vue'
import { VxTable } from 'veloxui'

// Set "editable: true" on columns you want to be editable
const columns = [
  { key: 'name', label: 'Name', editable: true },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role', editable: true },
  { key: 'status', label: 'Status' },
]

// Each row needs a unique "id" field (used internally to identify the row)
const data = ref([
  { id: 1, name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin', status: 'Active' },
  { id: 2, name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor', status: 'Active' },
  { id: 3, name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer', status: 'Inactive' },
  { id: 4, name: 'William Kim', email: 'will@email.com', role: 'Editor', status: 'Active' },
])

// Handle cell edits — update the data when a cell value changes
function onCellEdit(key, row, value) {
  const item = data.value.find(r => r.id === row.id)
  if (item) item[key] = value
}
</script>

<template>
  <!-- Double-click an editable cell to edit it -->
  <!-- Press Enter to save, Escape to cancel -->
  <VxTable :columns="columns" :data="data" @cell-edit="onCellEdit" bordered />
</template>

Remote Data ​

Передайте функцию fetch-data, чтобы загружать данные с бесконечной прокруткой — как в выпадающем списке select. Таблица загружает первую страницу при монтировании, затем подгружает новые строки по мере прокрутки к низу. При изменении сортировки или фильтра загрузка начинается заново с первой страницы.

IDNameEmail
vue
<script setup>
import { VxTable } from 'veloxui'

const columns = [
  { key: 'id', label: 'ID', width: 80 },
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
]

// "fetchData" receives { page, pageSize, sort, filter }
// Must return { data: [...rows], total: totalRowCount }
// The table calls this automatically:
//   - On mount (page 1)
//   - When scrolling near the bottom (next page, appended)
//   - When sort or filter changes (resets to page 1)
async function fetchUsers({ page, pageSize }) {
  const res = await fetch(`/api/users?page=${page}&limit=${pageSize}`)
  const json = await res.json()
  return { data: json.items, total: json.total }
}
</script>

<template>
  <!-- "fetch-data" enables server-side data with infinite scroll -->
  <!-- Set "max-height" to make the table scrollable -->
  <VxTable
    :columns="columns"
    :fetch-data="fetchUsers"
    :max-height="350"
    sortable
    bordered
  />
</template>

Row Click ​

Слушайте событие @row-click, чтобы обрабатывать клики по строкам.

vue
<script setup>
import { ref } from 'vue'
import { VxTable } from 'veloxui'

const columns = [
  { key: 'name', label: 'Name' },
  { key: 'email', label: 'Email' },
  { key: 'role', label: 'Role' },
]

const data = [
  { name: 'Olivia Martin', email: 'olivia.martin@email.com', role: 'Admin' },
  { name: 'Jackson Lee', email: 'jackson.lee@email.com', role: 'Editor' },
  { name: 'Isabella Nguyen', email: 'isabella.nguyen@email.com', role: 'Viewer' },
]

const clickedRow = ref(null)

function handleRowClick(row, index) {
  clickedRow.value = row
  console.log('Clicked row:', row, 'at index:', index)
}
</script>

<template>
  <p v-if="clickedRow">Выбрано: {{ clickedRow.name }}</p>

  <!-- @row-click fires when any row is clicked -->
  <VxTable :columns="columns" :data="data" @row-click="handleRowClick" bordered />
</template>

Summary Row ​

Используйте проп footer, чтобы добавить строку итогов/сводки. Ячейки футера поддерживают те же слоты footer-[key] для пользовательского содержимого.

ProductQtyPriceTotal
MacBook Pro 14"2$1,999.00$3,998.00
AirPods Pro5$249.00$1,245.00
Magic Keyboard3$299.00$897.00
Studio Display1$1,599.00$1,599.00
iPhone 15 Pro4$999.00$3,996.00
Total (5 items)15$11,735.00
vue
<script setup>
import { VxTable } from 'veloxui'

// Use "align" to right-align numeric columns
const columns = [
  { key: 'product', label: 'Product' },
  { key: 'qty', label: 'Qty', align: 'right' },
  { key: 'price', label: 'Price', align: 'right' },
  { key: 'total', label: 'Total', align: 'right' },
]

const data = [
  { product: 'MacBook Pro 14"', qty: 2, price: '$1,999.00', total: '$3,998.00' },
  { product: 'AirPods Pro', qty: 5, price: '$249.00', total: '$1,245.00' },
  { product: 'Magic Keyboard', qty: 3, price: '$299.00', total: '$897.00' },
  { product: 'Studio Display', qty: 1, price: '$1,599.00', total: '$1,599.00' },
  { product: 'iPhone 15 Pro', qty: 4, price: '$999.00', total: '$3,996.00' },
]

// "footer" has the same shape as data — it renders as a sticky bottom row
const footer = [
  { product: 'Total (5 items)', qty: 15, price: '', total: '$11,735.00' },
]
</script>

<template>
  <VxTable :columns="columns" :data="data" :footer="footer" bordered>
    <!-- Customize footer cells with "footer-[key]" slots -->
    <template #footer-product="{ value }">
      <span style="font-weight: 600;">{{ value }}</span>
    </template>
    <template #footer-total="{ value }">
      <span style="font-weight: 700;">{{ value }}</span>
    </template>
  </VxTable>
</template>

API ​

Props ​

PropTypeDefaultDescription
columnsTableColumn[]—Определения столбцов (обязательно)
dataRecord<string, any>[][]Массив данных строк
footerRecord<string, any>[]—Данные строки футера (того же вида, что и data)
borderedbooleanfalseВнешняя граница, скруглённые углы, разделители столбцов
stripedbooleanfalseЧередующиеся фоны строк
heightstring | number—Фиксированная высота с закреплённой шапкой
maxHeightstring | number—Максимальная высота с закреплённой шапкой
captionstring—Текст заголовка таблицы
scrollbar'auto' | 'hover' | 'always' | 'hidden''hover'Видимость полосы прокрутки
selectablebooleanfalseПоказывать чекбоксы строк
selectedany[]—Выбранные значения (v-model)
selectionKeystring'id'Поле строки, используемое как ключ выбора/развёртывания
draggablebooleanfalseВключить переупорядочивание строк перетаскиванием
resizableboolean | TableResizablefalseВключить изменение размера столбцов
sortablebooleanfalseВключить сортировку столбцов
sortTableSort | null—Состояние сортировки (v-model). Если опущено, используется внутреннее состояние
loadingbooleanfalseПоказать оверлей спиннера загрузки
expandablebooleanfalseПоказать переключатель развёртывания в каждой строке
expandedany[]—Ключи развёрнутых строк (v-model). Если опущено, используется внутреннее состояние
paginationboolean | TablePaginationfalseВключить пагинацию. true для встроенной, объект для управляемой
filterstring''Глобальный текстовый фильтр по всем видимым столбцам
groupBystring—Ключ столбца для группировки строк
columnTogglebooleanfalseПоказать встроенный выпадающий список видимости столбцов
columnOrderstring[]—Порядок ключей столбцов (v-model). Включает переупорядочивание перетаскиванием
fetchData(params: TableFetchParams) => Promise<TableFetchResult>—Серверные данные с бесконечной прокруткой. Подгружает при прокрутке, перезагружает при изменении сортировки/фильтра
pageCountnumber0Максимальное число страниц для загрузки. 0 означает безлимит (останавливается, когда data.length >= total)
scrollDistancenumber50Расстояние от низа (px) для запуска подгрузки

TableColumn ​

PropertyTypeDefaultDescription
keystring—Ключ поля данных (обязательно)
labelstring—Текст заголовка (обязательно)
widthstring | number—Ширина столбца
align'left' | 'center' | 'right''left'Выравнивание текста
fixed'left' | 'right'—Закрепить столбец у левого или правого края
resizableboolean | TableResizable—Переопределить resizable на уровне таблицы для этого столбца
sortableboolean—Переопределить sortable на уровне таблицы для этого столбца
editableboolean—Включить встроенное редактирование по двойному клику
render(row, index) => string—HTML-функция рендеринга для содержимого ячейки

TableResizable ​

PropertyTypeDefaultDescription
minWidthnumber50Минимальная ширина (px)
maxWidthnumberInfinityМаксимальная ширина (px)

TableSort ​

PropertyTypeDescription
keystringКлюч сортируемого столбца
order'asc' | 'desc'Направление сортировки

TablePagination ​

PropertyTypeDefaultDescription
pagenumber—Текущая страница (с 1)
pageSizenumber—Строк на странице
totalnumber—Общее число элементов (для серверной пагинации)
pageSizesnumber[][10, 20, 50, 100]Варианты размера страницы

TableFetchParams ​

PropertyTypeDescription
pagenumberТекущая страница (с 1)
pageSizenumberСтрок на странице
sortTableSort | nullТекущее состояние сортировки
filterstringТекущий текст фильтра

TableFetchResult ​

PropertyTypeDescription
dataRecord<string, any>[]Строки для текущей страницы
totalnumberОбщее число элементов (все страницы)

Slots ​

SlotPropsDescription
[column.key]{ row, value, index }Пользовательское содержимое ячейки
header-[column.key]{ column }Пользовательская ячейка заголовка
footer-[column.key]{ row, value, index }Пользовательская ячейка футера
expand{ row, index }Содержимое деталей развёрнутой строки
expand-icon{ row, expanded }Пользовательская иконка переключателя развёртывания
group{ group, count }Пользовательское содержимое заголовка группы
caption—Пользовательский заголовок таблицы
empty—Пользовательское пустое состояние

Events ​

EventPayloadDescription
update:selectedany[]Выбор изменён
update:dataRecord<string, any>[]Порядок строк изменён (перетаскиванием)
update:sortTableSort | nullСостояние сортировки изменено
update:expandedany[]Развёрнутые строки изменены
update:paginationTablePaginationPage/pageSize изменены
update:columnOrderstring[]Порядок столбцов изменён (перетаскиванием)
row-click(row, index)Клик по строке
cell-edit(key, row, value)Значение ячейки отредактировано
column-resize(key, width)Размер столбца изменён