Skip to content

DataTable ​

Tableau de données : tri, sélection de lignes, pagination, chargement et état vide, sur un vrai <table> accessible.

Exemples d'utilisation ​

Tri, sélection et pagination ​

Sélection : aucune

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

const columns = [
  { key: 'name', label: 'Client', sortable: true },
  { key: 'city', label: 'Ville', sortable: true },
  { key: 'orders', label: 'Commandes', sortable: true, align: 'end' },
  { key: 'status', label: 'Statut' }
]
const rows = ref([/* { id, name, city, orders, status } */])
const sort = ref(null)
const page = ref(1)
const selected = ref([])
</script>

<template>
  <SuDataTable
    v-model:sort="sort"
    v-model:page="page"
    v-model:selected="selected"
    :columns="columns"
    :rows="rows"
    caption="Clients"
    selectable
    :page-size="5"
  >
    <template #cell-status="{ value }">
      <SuTag :label="value" size="sm" />
    </template>
  </SuDataTable>
</template>

Format, alignement et colonne d'actions ​

format transforme l'affichage sans changer la valeur triée ; hideLabel masque visuellement un en-tête (colonne d'actions) qui reste lu.

js
const columns = [
  { key: 'revenue', label: 'Chiffre d’affaires', sortable: true, align: 'end',
    format: (value) => new Intl.NumberFormat('fr-FR', { style: 'currency', currency: 'EUR' }).format(value) },
  { key: 'since', label: 'Client depuis', sortable: true,
    format: (value) => value.toLocaleDateString('fr-FR') },
  { key: 'actions', label: 'Actions', hideLabel: true, align: 'end' }
]

Tri et pagination serveur ​

Avec manual, les lignes reçues sont affichées telles quelles : le tableau émet update:sort et update:page, le serveur renvoie la page triée et total donne le nombre de pages.

vue
<SuDataTable
  v-model:sort="sort"
  v-model:page="page"
  :columns="columns"
  :rows="pageRows"
  :total="total"
  :page-size="20"
  :loading="loading"
  manual
  caption="Commandes"
  @update:sort="fetchPage"
  @update:page="fetchPage"
/>

Chargement et état vide ​

vue
<SuDataTable :columns="columns" :rows="rows" :loading="loading" />
<SuDataTable :columns="columns" :rows="[]" empty-text="Aucun client ne correspond aux filtres." />

API ​

Props ​

PropTypeDéfautDescription
columnsDataTableColumn[][]Colonnes
rowsRecord<string, any>[][]Lignes
rowKeystring | (row) => string | number'id'Identifiant d'une ligne
captionstring-Titre du tableau, nom de la zone (ou slot caption)
captionHiddenbooleanfalseTitre lu mais masqué visuellement
selectablebooleanfalseCases à cocher de sélection
rowLabel(row) => stringpremière colonneNom d'une ligne pour sa case
pageSizenumber-Lignes par page (pagination)
manualbooleanfalseTri et pagination faits par le serveur
totalnumber-Total de lignes en mode manual
loadingbooleanfalseChargement : squelettes et aria-busy
emptyTextstring'Aucune donnée'Texte de l'état vide (ou slot empty)
stripedbooleanfalseLignes alternées
size'sm' | 'md' | 'lg''md'Densité
stickyHeaderbooleanfalseEn-tête collant (avec maxHeight)
maxHeightstring-Hauteur maximale (défilement)
localestringlocale des composantsLangue du tri alphabétique

DataTableColumn ​

PropriétéTypeDescription
keystringPropriété de la ligne
labelstringEn-tête
sortablebooleanColonne triable
align'start' | 'center' | 'end'Alignement (end : chiffres tabulaires)
widthstringLargeur
format(value, row) => stringTexte affiché
sortFn(a, b) => numberComparaison personnalisée
hideLabelbooleanEn-tête masqué visuellement

v-model ​

ModèleTypeDescription
v-model:sort{ key, direction: 'asc' | 'desc' } | nullTri courant
v-model:pagenumberPage courante
v-model:selected(string | number)[]Identifiants des lignes cochées

Slots ​

SlotPropsDescription
cell-{key}{ row, value, index }Contenu d'une cellule
header-{key}{ column }Contenu d'un en-tête
caption-Titre riche
empty-État vide (ex. SuEmptyState)

Accessibilité ​

  • Vrai <table> : <caption>, en-têtes de colonnes (scope="col") et de lignes (première colonne, scope="row").
  • Tri : bouton dans l'en-tête, aria-sort sur la colonne triée, annonce « Trié par Ville, ordre croissant ». Ordre alphabétique de la langue (accents, nombres dans le texte), cellules vides toujours à la fin.
  • Sélection : chaque case est nommée par la ligne (« Sélectionner Émile A. ») ; la case « Tout sélectionner » porte l'état mixte et agit sur les lignes affichées.
  • La zone de défilement est focusable (défilement au clavier) et nommée par le titre.
  • Chargement : aria-busy="true" et texte « Chargement en cours… » lu dans le tableau.

Publié sous licence MIT.