Démarrage Vue et Nuxt
Une table Vue native complète, un client Query partagé et l’intégration Nuxt.
Construisez la même table produits avec une configuration Vue native et un client Vue Query partagé. Installez le registre Vue avant de copier ces fichiers. Les concepts expliquent le fonctionnement commun.
Structure du projet
products/
shared/products.ts
vue/product-config.ts
vue/product-actions.ts
vue/products.vue
vue/main.ts1. Définir les enregistrements
export interface Product extends Record<string, unknown> {
active: boolean;
id: string;
image: string;
name: string;
price: number;
/** Civil dates, inclusive at both ends: the window a batch is being restocked. */
restockFrom: string;
restockTo: string;
status: "draft" | "active" | "archived";
stock: number;
tags: string[];
updatedAt: string;
}
export const products: Product[] = [
{
id: "desk",
name: "Oak desk",
price: 420,
stock: 12,
status: "active",
active: true,
tags: ["office", "wood"],
image: "https://placehold.co/640x480/png?text=Oak+desk",
restockFrom: "2026-09-14",
restockTo: "2026-09-18",
updatedAt: "2026-09-01T09:00:00Z",
},
{
id: "lamp",
name: "Desk lamp",
price: 65,
stock: 0,
status: "draft",
active: false,
tags: ["office"],
image: "https://placehold.co/640x480/png?text=Desk+lamp",
restockFrom: "2026-09-17",
restockTo: "2026-09-24",
updatedAt: "2026-09-02T09:00:00Z",
},
{
id: "chair",
name: "Studio chair",
price: 180,
stock: 6,
status: "active",
active: true,
tags: ["office", "seating"],
image: "https://placehold.co/640x480/png?text=Studio+chair",
restockFrom: "2026-09-23",
restockTo: "2026-10-02",
updatedAt: "2026-09-03T09:00:00Z",
},
];2. Configurer la table
import { defineTableConfig } from "@/components/ui/yayaw-table-vue";
export const productConfig = defineTableConfig({
id: "products",
translations: { namespace: "products", keys: {} },
columns: {
definitions: [
{ id: "name", header: "Name", type: "text" },
{ id: "price", header: "Price", type: "number" },
{ id: "stock", header: "Stock", type: "number" },
{
id: "status",
header: "Status",
type: "select",
options: [
{ label: "Draft", value: "draft" },
{ label: "Active", value: "active" },
{ label: "Archived", value: "archived" },
],
},
],
order: ["name", "price", "stock", "status"],
visible: ["name", "price", "stock", "status"],
mandatory: ["name"],
sort: [{ id: "name", desc: false }],
},
table: {
allowCreate: false,
allowEdit: false,
allowDelete: false,
allowDuplicate: false,
allowBulkEdit: false,
allowBulkDelete: false,
enableRowSelection: false,
enableViews: false,
syncUrl: false,
defaultPageSize: 10,
},
});
export const getTableConfig = (tableType: string) =>
tableType === "products" ? productConfig : undefined;3. Connecter les actions de liste
Cet adaptateur implémente le même contrat de requête que React. La recherche porte sur les noms, références, prix, stocks, statuts, booléens et tags. Les filtres et le tri s’appliquent avant la pagination. Le résultat contient les totaux. Les enregistrements sont fictifs et restent en mémoire.
import type { TableActions } from "@/components/ui/yayaw-table-vue/types";
import { products } from "../shared/products";
import { listRecords } from "./list-records";
export const productActions: TableActions = {
list: (input) => listRecords(products, input),
};
export const getTableActions = (tableType: string) =>
tableType === "products" ? productActions : undefined;Adaptateur de liste complet
import {
compatibleListParams,
matchesContractFilter,
normalizeFilterEnvelope,
recordValue,
} from "@/components/ui/yayaw-table-vue/table-contracts";
export function listRecords<T extends Record<string, unknown>>(
rows: T[],
input: unknown
) {
const params = compatibleListParams(recordValue(input));
const page = Number(params.page);
const limit = Number(params.limit);
const search = String(params.search).toLowerCase();
const filters = Object.entries(recordValue(params.filters));
const advanced = normalizeFilterEnvelope(params.advancedFilters).filters;
const matching = rows.filter((product) => {
const row: Record<string, unknown> = product;
const matchesSearch =
!search ||
["name", "reference", "price", "stock", "status", "active", "tags"].some(
(key) => {
const value = product[key];
return (
value !== null &&
value !== undefined &&
String(value).toLowerCase().includes(search)
);
}
);
const matchesColumns = filters.every(([id, value]) =>
matchesContractFilter(row[id], {
type: typeof row[id] === "number" ? "number" : "text",
operator: Array.isArray(value) ? "isAnyOf" : "contains",
values: Array.isArray(value) ? value : [value],
})
);
const matchesRule = (rule: Record<string, unknown>) =>
matchesContractFilter(row[String(rule.columnId)], rule);
const matchesAdvanced =
advanced.length === 0 ||
(params.advancedFilterJoin === "or"
? advanced.some(matchesRule)
: advanced.every(matchesRule));
return matchesSearch && matchesColumns && matchesAdvanced;
});
const sorting = Object.entries(recordValue(params.orderBy));
matching.sort((left, right) => {
for (const [id, direction] of sorting) {
const a = (left as Record<string, unknown>)[id];
const b = (right as Record<string, unknown>)[id];
const comparison =
typeof a === "number" && typeof b === "number"
? a - b
: String(a ?? "").localeCompare(String(b ?? ""));
if (comparison !== 0) {
return direction === "desc" ? -comparison : comparison;
}
}
return String(left.id).localeCompare(String(right.id));
});
return Promise.resolve({
// Model a server response: later store mutations must not alter cached rows.
data: structuredClone(matching.slice((page - 1) * limit, page * limit)),
meta: {
pageCount: Math.max(1, Math.ceil(matching.length / limit)),
totalCount: matching.length,
},
});
}4. Afficher le composant
Données de démonstration. Les modifications restent dans cet aperçu.
<script setup lang="ts">
import type { ExamplePresentation } from "./presentation";
defineProps<ExamplePresentation>();
import { YayawDataTable } from "@/components/ui/yayaw-table-vue";
import { getTableActions } from "./product-actions";
import { productConfig } from "./product-config";
</script>
<template>
<YayawDataTable v-bind="$props"
:config="productConfig"
:get-table-actions="getTableActions"
:get-row-id="row => String(row.id)"
table-id="products-example"
table-type="products"
:title="title ?? 'Products'"
/>
</template>5. Installer le client Query partagé
import { QueryClient, VueQueryPlugin } from "@tanstack/vue-query";
import { createApp } from "vue";
import Products from "./products.vue";
import "@/components/ui/yayaw-table-vue/styles.css";
const app = createApp(Products);
app.use(VueQueryPlugin, { queryClient: new QueryClient() });
app.mount("#app");Montez Products dans un élément avec id="app", ou réutilisez le point d’entrée et le provider de votre application. Gardez les styles du registre dans l’entrée CSS de l’application. Vue n’utilise pas Nuqs.
Données locales
Pour une table entièrement locale, passez :data="products" et retirez get-table-actions. Vue applique les filtres, le tri et la pagination à ce tableau. Pour une source distante, utilisez les actions : une page serveur isolée passée comme donnée locale ne représente pas tout le jeu de données.
Nuxt et SSR
Installez VueQueryPlugin dans un plugin Nuxt avec un nouveau QueryClient par application/requête. Réutilisez le mécanisme de déshydratation et d’hydratation du projet pour les requêtes préchargées. Importez les styles du registre dans la configuration CSS Nuxt. Isolez les rendus personnalisés qui nécessitent le navigateur et n’utilisez initialData, initialRowCount et initialPageCount que pour la requête initiale correspondante.
Notifications de l’application
Montez un unique Toaster de vue-sonner à la racine de l’application et importez vue-sonner/style.css si vous utilisez directement Sonner. Toutes les instances de table le partagent. Les formulaires conservent leurs erreurs de validation et de reprise près des champs.
Ajouter une fonctionnalité
La suite de la documentation est organisée par fonctionnalité. Utilisez l’onglet Vue dans les guides colonnes, formulaires, actions groupées et vues. La référence des actions explique les alias de requête et de résultat partagés avec React.
Sections du guide précédent
Vue 3 et Nuxt
Consultez le guide actuel : concepts.
Couverture fonctionnelle
Consultez le guide actuel : compatibility.
Prérequis d'exécution
Consultez le guide actuel : compatibility.
Lancer le workspace Vue
Consultez le guide actuel : installation.
Migrer depuis TanStack Table 8
Consultez le guide actuel : concepts.
Enregistrer le package
Consultez le guide actuel : installation.
Configurer une table
Consultez le guide actuel : configuration.
Densité du tableau
Consultez le guide actuel : layout.
Actions de toolbar du catalogue
Consultez le guide actuel : actions.
Connecter les actions côté serveur
Consultez le guide actuel : actions.
Champ de formulaire tablePicker
Consultez le guide actuel : table-picker.
Partager le cache Vue Query
Consultez le guide actuel : query-integration.
Construire l'item de registre shadcn-vue
Consultez le guide actuel : installation.
Correspondance React vers Vue
Consultez le guide actuel : compatibility.
Comportements communs à React et Vue
Consultez le guide actuel : compatibility.
Sélection multiple et sauvegarde inline
Consultez le guide actuel : inline-editing.
Un type de colonne dans toute l’interface
Consultez le guide actuel : columns.
Formulaires générés structurés
Consultez le guide actuel : form-layout.
Lignes regroupées
Consultez le guide actuel : grouping-calculations.
Contrôles des cartes et résultats vides
Consultez le guide actuel : gallery.
Barre de filtres optionnelle
Consultez le guide actuel : filtering.
Vues favorites personnelles
Consultez le guide actuel : views.
Consultation et activité d’une entrée
Consultez le guide actuel : record-details.