@qnx/vuetify

April 10, 2026 · View on GitHub

@qnx/vuetify is a Vue 3 component library built on top of Vuetify that simplifies forms, data tables, and lists. It handles validation, server communication, error display, and data management internally — reducing boilerplate and keeping your templates clean.

Installation

npm install @qnx/vuetify
# or
yarn add @qnx/vuetify
# or
pnpm add @qnx/vuetify
# or
bun add @qnx/vuetify

Peer Dependencies

Install the required peer dependencies alongside the library:

npm install vuetify@^4.0.0 pinia vee-validate axios @qnx/composables
DependencyVersionNotes
vuetify^4.0.0Required
pinia3.xRequired
vee-validate*Required
axios*Required for HTTP requests
@qnx/composables*Required
@tinymce/tinymce-vue*Optional — only for VqTextEditor
yup*Optional — for schema-based validation with vee-validate

Basic Usage

<script setup>
import { VqForm, VqTextField } from '@qnx/vuetify'
import { object, string } from 'yup'

const validationSchema = object({
  name: string().required(),
  email: string().required().email(),
})

const initialValues = { name: 'Test User', email: 'test@gmail.com' }

const onSuccess = (res) => console.log(res)
</script>

<template>
  <VqForm
    id="create-user"
    action="user/create"
    method="POST"
    :validation-schema="validationSchema"
    :initial-values="initialValues"
    @submited-success="onSuccess"
  >
    <VqTextField name="name" label="Name" placeholder="Name" />
    <VqTextField name="email" label="Email" placeholder="Email" />
    <button type="submit">Submit</button>
  </VqForm>
</template>

Components

Form Components

These components must be used inside a VqForm or useVqForm wrapper. They automatically connect to form state, handle validation display, and bind field values.

ComponentDescription
VqFormForm wrapper. Handles submission, validation, and server communication via axios.
VqTextFieldText input bound to vee-validate form state.
VqTextareaTextarea input bound to form state.
VqAutocompleteAutocomplete/select input bound to form state.
VqCheckboxCheckbox input bound to form state.
VqDatePickerDate picker input bound to form state.
VqTimePickerTime picker input bound to form state.
VqColorPickerColor picker input bound to form state.
VqOtpInputOTP (one-time password) input bound to form state.
VqFileInputFile input bound to form state.
VqFileUploadFile upload input with upload handling.
VqSubmitBtnSubmit button that reflects form busy/loading state.

VqForm Props

PropTypeRequiredDefaultDescription
idstringYesUnique identifier for the form. Used internally to coordinate with submit buttons and filters.
actionstringYesAPI endpoint URL for form submission.
methodstringNo"POST"HTTP method (POST, PUT, PATCH, etc.).
initialValuesobjectNoundefinedInitial field values. Resets the form when this value changes.
validationSchemaobjectNoundefinedYup validation schema.
valuesSchemaobjectNoundefinedMaps nested response fields to flat form fields.
formDatabooleanNofalseWhen true, submits as multipart/form-data instead of JSON.
successResponseHandlerfunctionNoCustom handler for successful responses. Overrides the default emit.
errorResponseHandlerfunctionNoCustom handler for error responses. Overrides the default error display.

VqForm Events

EventPayloadDescription
submited-successApiResponseEmitted on successful server response.
submited-errorApiResponseEmitted when the server returns a validation error.
submited-client-errorEmitted on client-side validation failure.

Data Table Components

ComponentDescription
VqDataTableServer-side data table built on Vuetify's VDataTableServer. Handles pagination, sorting, and filter integration.
VqSerialNoRenders a <td> with the row's serial number. Use inside VqDataTable item slots.
VqDatatableItemActionAction button (delete/change-status) for a table row. Opens a confirmation dialog before making the API call.

VqDataTable Props

PropTypeRequiredDefaultDescription
idstringYesUnique identifier. Must match the id used in the paired VqTableFilter.
actionstringYesAPI endpoint for fetching table data.
methodstringNo"GET"HTTP method for data fetching.
pagenumberNo1Initial page number.
itemsPerPagenumberNo10Number of rows per page.
sortBySortByValue[]No[{ key: "name", order: "asc" }]Default sort configuration.

VqDatatableItemAction Props

PropTypeRequiredDefaultDescription
idstringYesTable ID. Used to trigger a reload after the action completes.
itemIdstringNo"0"The ID of the row item to act on.
actionstringNo"user/change-status"API endpoint. The itemId is appended as a path segment: action/itemId.
methodstringNo"PUT"HTTP method for the action request.
titlestringNo"Confirmation"Confirmation dialog title.
descriptionstringNo"Are you sure to want delete this record?"Confirmation dialog message.
iconstringNomdiDeleteMDI icon path for the action button.

List Components

ComponentDescription
VqListInfinite-scroll list built on Vuetify's VList. Fetches paginated data from an API and integrates with VqTableFilter.
VqListLoadMoreBtnButton that loads the next page of items. Must be used inside a VqList.
VqTableFilterFilter form that connects to a paired VqDataTable or VqList by ID. Triggers a data reload on change.

VqList Props

PropTypeRequiredDefaultDescription
idstringYesUnique identifier. Must match the id used in a paired VqTableFilter.
actionstringYesAPI endpoint for fetching list data.
pageSizenumberNo10Number of items loaded per page.

VqTableFilter Props

PropTypeRequiredDefaultDescription
idstringYesMust match the id of the VqDataTable or VqList it filters.

Integration Components

ComponentDescription
VqTextEditorRich text editor using TinyMCE. Requires @tinymce/tinymce-vue as an additional peer dependency.

Composables

useVqForm(options)

An alternative to <VqForm> for cases where you need programmatic access to form state (errors, values, resetForm, etc.) from outside the form component.

<script setup>
import { useVqForm } from '@qnx/vuetify'
import { object, string } from 'yup'

const { wrapper: MyForm, resetForm } = useVqForm({
  formId: 'edit-user',
  validationSchema: object({ name: string().required() }),
  initialValues: { name: '' }
})
</script>

<template>
  <MyForm action="user/update" method="PUT">
    <VqTextField name="name" label="Name" />
    <VqSubmitBtn />
  </MyForm>
</template>

useVqDataTable<TValue>()

Returns a strongly-typed wrapper around VqDataTable. Use this when you need TypeScript inference for item slot props.

import { useVqDataTable } from '@qnx/vuetify'

interface User { id: number; name: string; email: string }

const UserTable = useVqDataTable<User>()

useVqList<TValue>()

Returns a strongly-typed wrapper around VqList. Use this when you need TypeScript inference for the default slot's items prop.

import { useVqList } from '@qnx/vuetify'

interface Post { id: number; title: string }

const PostList = useVqList<Post>()

collectVqHeaders(headers)

Prepends a # (serial number) column to a headers array for use with VqDataTable.

import { collectVqHeaders } from '@qnx/vuetify'

const headers = collectVqHeaders([
  { title: 'Name', key: 'name' },
  { title: 'Email', key: 'email' },
])
// → [{ title: '#', sortable: false }, { title: 'Name', key: 'name' }, ...]

collectVqHeaders + VqSerialNo Example

<template>
  <VqDataTable id="users" action="users" :headers="headers">
    <template #item="{ item, index }">
      <tr>
        <VqSerialNo :index="index + 1" />
        <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>

Filter + Table Pattern

VqTableFilter and VqDataTable (or VqList) are linked by a shared id. When filter values change, the table automatically reloads.

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

  <VqDataTable id="users" action="users" :headers="headers" />
</template>

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

MIT License © 2023-PRESENT Yatendra Kushwaha