Référence DataTable
Référence des props et usages du composant DataTable unifié
Référence DataTable
Composant point d'entrée unique : vous passez config + actions en props ; il compose le provider, l'UI et la logique de table en interne.
import { DataTable } from "@/components/ui/yayaw-table";Pour un setup minimal fonctionnel, il vous faut tableType, getTableConfig et getTableActions. Voir Provider & Setup pour la vue complète et le layout Next.js (NuqsAdapter, QueryClientProvider).
Si aucun QueryClient n'est disponible depuis le contexte (et qu'aucune prop queryClient explicite n'est fournie), DataTable lève maintenant une erreur runtime explicite.
Props
Liste des props disponibles pour configurer DataTable.
tableType
Type de configuration de table. Utilisé pour résoudre config et actions (getTableConfig("products"), getTableActions("products")).
<DataTable tableType="products" />Requis : true
tableId
Identifiant stable de l'instance de table pour l'état d'URL, le cache, la sélection, la pagination et la toolbar. Par défaut : tableType.
Utilisez-le quand une même table affiche plusieurs modèles métier mais doit garder un seul état partagé.
Type : string
formType
Type de formulaire par défaut pour create/edit. Par défaut : tableType. La config de table peut le surcharger avec form.createFormType, form.editFormType ou form.resolveEditFormType(row).
Type : string
getTableConfig
Fonction qui retourne la configuration table/colonnes pour le tableType donné. Requise pour définir colonnes, tri, visibilité et options.
Type : (tableType: string) => Config | undefined
getTableActions
Fonction qui retourne les actions (list, create, update, delete, bulk, etc.) pour le tableType. list est obligatoire pour les données server-driven.
Type : (tableType: string) => TableActions | undefined
getFormConfig
Fonction qui retourne les définitions de champs pour les dialogs create/edit et bulk edit. Optionnelle, mais nécessaire pour les formulaires intégrés.
Type : (formType: string, ctx?: FormConfigContext) => FormConfig | undefined
ctx contient { mode, tableId, tableType, formType, row, initialData, values }, ce qui permet de changer les champs selon la ligne éditée ou les valeurs courantes du formulaire.
queryClient
Instance TanStack Query explicite optionnelle. Yayaw Table n'en crée plus en interne. Dans la plupart des apps, utilisez un QueryClientProvider partagé au niveau app et omettez cette prop.
Type : QueryClient
initialData
Lignes injectées dans le premier état client de la table. Utilisez cette prop quand un Server Component a déjà chargé la première page et que vous voulez hydrater la table avec des données utiles avant le refresh client TanStack Query.
Type : Record<string, unknown>[] | Par défaut : []
initialPageCount
Nombre total de pages correspondant à initialData. Fournissez-le pour les jeux de données paginés côté serveur afin que le premier rendu garde les bons contrôles de pagination au lieu de supposer une seule page.
Type : number | Par défaut : 1 quand initialData est présent
initialRowCount
Nombre total de lignes correspondant à initialData. Fournissez-le quand le serveur connaît le total filtré complet de la première page.
Type : number | Par défaut : initialData.length
className
Classes additionnelles appliquées au wrapper racine.
Type : string | Par défaut : undefined
loadingOverlay
Surcouche de chargement personnalisée affiché pendant le chargement des données.
Type : React.ReactNode | Par défaut : spinner interne
<DataTable tableType="products" loadingOverlay={<MySpinner />} />onRowSelectionChange
Callback déclenché quand la sélection de lignes change.
Type : (rows: Row<Record<string, unknown>>[]) => void | Par défaut : undefined
activeRowId
Marque une ligne comme active. Utile pour les tables master-detail où la table est la surface d'inventaire et un autre panneau affiche la ligne sélectionnée.
Type : string | Par défaut : undefined
getRowId
Retourne un id de ligne stable pour le surlignage actif, la sélection et les métadonnées de ligne. Si omis, la table utilise les champs id courants puis l'id React Table.
Type : (row: Record<string, unknown>) => string | Par défaut : undefined
onRowActivate
Callback déclenché quand table.rowClickMode vaut 'activate' et qu'une zone non interactive de ligne ou de carte est cliquée.
Type : (row: Record<string, unknown>, event: React.MouseEvent) => void | Par défaut : undefined
onRowClick
Callback déclenché par les interactions de lien, y compris les clics de ligne en mode row-link et les boutons lien de Gallery. Utilisez-le pour router via votre app ou suivre de l'analytics au lieu de dépendre du comportement navigateur par défaut.
Type : (url: string, row: Record<string, unknown>, event: React.MouseEvent) => void | Par défaut : undefined
onBulkEdit
Gère l'édition de masse des lignes sélectionnées.
Type : (rows: Row<Record<string, unknown>>[]) => BulkActionResult | void | Promise<BulkActionResult | void> | Par défaut : actions provider
onBulkDelete
Gère la suppression de masse des lignes sélectionnées.
Type : (rows: Row<Record<string, unknown>>[]) => BulkActionResult | BulkDeleteExecutionOutcome | void | Promise<...> | Par défaut : provider bulkDelete / delete
onBulkCopy
Gère la duplication de masse des lignes sélectionnées.
Type : (rows: Row<Record<string, unknown>>[]) => BulkActionResult | void | Promise<BulkActionResult | void> | Par défaut : copie clipboard interne
onExport
Surcharge le comportement d'export de la barre d'outils. Appelé avec toutes les lignes correspondant à l'état courant (search/filters/sort).
Type : (rows: Record<string, unknown>[]) => void \| Promise<void> | Par défaut : export CSV interne
onBulkExport
Surcharge le comportement d'export bulk. Appelé avec les lignes sélectionnées.
Type : (rows: Row<Record<string, unknown>>[]) => void \| Promise<void> | Par défaut : export CSV interne
toolbarActions
Injecte des actions personnalisées dans la barre d'outils principale. Accepte un tableau statique ou une fonction recevant le contexte courant.
Type : ToolbarAction[] | ((ctx: ToolbarActionContext) => ToolbarAction[]) | Par défaut : undefined
toolbarActionsPlacement
Contrôle l'emplacement des actions personnalisées par rapport aux actions natives.
Type : "before-create" | "between-create-export" | "after-export" | Par défaut : "between-create-export"
ToolbarAction et ToolbarActionContext
type ToolbarAction = {
id: string;
label: string;
icon?: ReactNode;
onClick: (ctx: ToolbarActionContext) => void | Promise<void>;
disabled?: boolean | ((ctx: ToolbarActionContext) => boolean);
loading?: boolean;
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive";
showInIconMode?: boolean; // true par défaut
tooltip?: string;
};
type ToolbarActionContext = {
tableId: string;
actionsAsIcons: boolean;
isMobile: boolean;
isCreateEnabled: boolean;
isExportEnabled: boolean;
isExporting: boolean;
hasListAction: boolean;
selectedRows: Row<Record<string, unknown>>[];
selectedOriginalRows: Record<string, unknown>[];
selectedRowIds: string[];
selectedCount: number;
tableActions?: TableActions;
};Table Multi-Modèles
Une seule table peut garder un tableId commun tout en séparant la config table et la config formulaire :
<DataTable
tableId="cms-entries"
tableType="content-index"
formType="content-entry"
getTableConfig={(tableType) => ({
...configs[tableType],
form: {
createFormType: "content-entry",
resolveEditFormType: (row) => `${row.modelId}-entry`,
},
})}
getFormConfig={(formType, ctx) =>
buildEntryForm({
formType,
modelId: String(ctx?.values?.modelId ?? ctx?.row?.modelId ?? ""),
})
}
customBulkActions={(ctx) => [
{
id: "publish-selected",
label: "Publish",
icon: Send,
disabled: ctx.selectedCount === 0,
onClick: async () => publishEntries(ctx.selectedOriginalRows),
},
{
id: "archive-selected",
label: "Archive",
icon: Archive,
variant: "destructive",
disabled: ctx.selectedCount === 0,
confirm: {
title: "Archive selected entries?",
description: `Archive ${ctx.selectedCount} selected entries.`,
},
onClick: async () => archiveEntries(ctx.selectedOriginalRows),
},
]}
/>Ici cms-entries pilote URL/cache/sélection, content-index pilote les colonnes et filtres, et chaque ligne peut ouvrir son propre type de formulaire d'édition.
Données initiales server-first
Pour les pages Next.js App Router, chargez la première page dans un Server Component, puis passez les lignes et la pagination à un petit Client Component qui rend DataTable.
// app/products/page.tsx
import { listProducts } from "./actions/products";
import { ProductsTableClient } from "./products-table-client";
export default async function ProductsPage() {
const initial = await listProducts({ limit: 10, page: 1 });
return (
<ProductsTableClient
initialData={initial.data}
initialPageCount={initial.meta.pageCount}
initialRowCount={initial.meta.totalCount}
/>
);
}// app/products/products-table-client.tsx
"use client";
import { DataTable } from "@/components/ui/yayaw-table";
import { listProducts } from "./actions/products";
import { getTableConfig } from "./table-config";
export function ProductsTableClient({
initialData,
initialPageCount,
initialRowCount,
}: {
initialData: Record<string, unknown>[];
initialPageCount: number;
initialRowCount: number;
}) {
return (
<DataTable
getTableActions={() => ({ list: listProducts })}
getTableConfig={getTableConfig}
initialData={initialData}
initialPageCount={initialPageCount}
initialRowCount={initialRowCount}
tableType="products"
/>
);
}initialData est uniquement la première valeur de cache. Tri, filtres, pagination, retry et refresh continuent d'appeler votre action getTableActions().list via TanStack Query, donc l'autorisation et l'accès aux données restent dans votre couche serveur.
enableAdvancedFilters
Active l'UI de filtres avancés si disponible dans votre configuration.
Type : boolean | Par défaut : false
columnTypeMapping
Mappe vos types backend dynamiques vers les types de rendu internes.
Type : Record<string, 'text' | 'number' | 'date' | 'option' | 'multiOption'> | Par défaut : {}
Usage
<DataTable
tableType="products"
loadingOverlay={<MySpinner />}
onRowSelectionChange={(rows) => console.log(rows)}
onBulkDelete={(rows) => console.log("delete", rows.length)}
onExport={(rows) => console.log("export all", rows.length)}
onBulkExport={(rows) => console.log("export selected", rows.length)}
/>Action personnalisée en mode texte :
<DataTable
tableType="products"
toolbarActions={[
{
id: "recalculate-prices",
label: "Recalculate prices",
onClick: async () => {
await recalculatePrices();
},
variant: "secondary",
},
]}
/>Action personnalisée en mode icône avec tooltip et placement explicite :
<DataTable
tableType="products"
toolbarActions={(ctx) => [
{
id: "recalculate-prices",
label: "Recalculate prices",
tooltip: "Recalculate prices",
icon: <RefreshCw className="h-4 w-4" />,
disabled: () => !ctx.hasListAction || ctx.isExporting,
onClick: async () => {
await recalculatePrices();
},
},
]}
toolbarActionsPlacement="between-create-export"
/>Compatibilité: si toolbarActions n'est pas défini, le comportement de la toolbar reste inchangé.
Voir aussi :