Skip to content

Data Components

Data components display and manage server-side data with automatic pagination, sorting, filtering, and infinite scroll.


Available Components

ComponentDescriptionLink
VqDataTableServer-side paginated data table with sorting and filter integration→ Docs
useVqDataTable<T>Type-safe wrapper for VqDataTable→ Docs
collectVqHeadersUtility to prepend a # serial column to table headers→ Docs
VqSerialNoSerial number <td> cell for use in table row slots→ Docs
VqDatatableItemActionRow action button (delete/status) with confirmation dialog→ Docs
VqListInfinite-scroll list with filter integration→ Docs
useVqList<T>Type-safe wrapper for VqList→ Docs
VqTableFilterFilter form that connects to VqDataTable or VqList by shared id→ Docs
VqListLoadMoreBtn"Load More" button for VqList — uses inject, no props needed→ Docs
MessageQueueRoot-level snackbar notification queue — place once in App.vue→ Docs

How It Works

Table + Filter Pattern

Connect VqTableFilter and VqDataTable with the same id. When filter fields change, the table reloads automatically.

vue
<script setup>
import { VqDataTable, VqTableFilter, VqTextField, collectVqHeaders } from "@qnx/vuetify";

const headers = collectVqHeaders([
  { title: "Name", key: "name" },
  { title: "Email", key: "email" },
  { title: "Actions", key: "actions", sortable: false },
]);
</script>

<template>
  <VqTableFilter id="users">
    <VqTextField name="search" label="Search" />
  </VqTableFilter>

  <VqDataTable id="users" action="users/list" :headers="headers">
    <template #item="{ item, index }">
      <tr>
        <td>{{ index }}</td>
        <td>{{ item.name }}</td>
        <td>{{ item.email }}</td>
        <td>
          <VqDatatableItemAction
            id="users"
            :item-id="String(item.id)"
            action="users/delete"
            method="DELETE"
          />
        </td>
      </tr>
    </template>
  </VqDataTable>
</template>

Infinite Scroll List Pattern

vue
<template>
  <VqTableFilter id="posts">
    <VqTextField name="search" label="Search" />
  </VqTableFilter>

  <VqList id="posts" action="posts/list" :page-size="15" v-slot="{ items, loading }">
    <v-list-item v-for="post in items" :key="post.id" :title="post.title" />
    <v-skeleton-loader v-if="loading" type="list-item@3" />
    <VqListLoadMoreBtn />
  </VqList>
</template>

Import

typescript
import {
  VqDataTable,
  useVqDataTable,
  collectVqHeaders,
  VqSerialNo,
  VqDatatableItemAction,
  VqList,
  useVqList,
  VqTableFilter,
  VqListLoadMoreBtn,
  MessageQueue,
} from "@qnx/vuetify";