Actions bulk
Flux de confirmation et contrat des callbacks pour copy, delete, edit et export
Utilisez TableConfig.presentation à la racine pour une surface commune de consultation, création, édition et édition groupée, avec un choix mobile facultatif. Le défaut est un drawer à droite sur tous les écrans. Consultez la présentation commune des fiches pour la configuration et la migration.
Édition groupée par champ
Cet exemple complet utilise le démarrage et les fichiers communs des recettes. La référence ci-dessous détaille les options et les fragments d’intégration.
import { defineTableConfig } from "@/components/ui/yayaw-table/config/helpers";
import { productConfig } from "./product-config";
export const adminConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
layoutPreset: "admin",
defaultPageSize: 2,
pageSizeOptions: [2, 10, 20],
enableRowSelection: true,
enableMultiRowSelection: true,
preserveSelectionOnQuery: true,
allowEdit: true,
allowBulkEdit: true,
canEditRow: (row) => row.status !== "archived",
canSelectRow: (row) => row.status !== "archived",
bulkExport: true,
},
form: { editFormType: "products" },
});import { defineTableConfig } from "@/components/ui/yayaw-table-vue/config";
import { productConfig } from "./product-config";
export const adminConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
layoutPreset: "admin",
defaultPageSize: 2,
pageSizeOptions: [2, 10, 20],
enableRowSelection: true,
enableMultiRowSelection: true,
preserveSelectionOnQuery: true,
allowEdit: true,
allowBulkEdit: true,
canEditRow: (row) => row.status !== "archived",
canSelectRow: (row) => row.status !== "archived",
bulkExport: true,
},
form: { editFormType: "products" },
});Actions bulk
Sélectionner une plage avec Maj-clic
Dans React et Vue, activez la sélection de lignes et la sélection multiple pour sélectionner une plage en mode tableau :
// Inside defineTableConfig({ table: { ... } }).
enableRowSelection: true,
enableMultiRowSelection: true,Cliquez sur la case d’une ligne pour définir le point de départ, puis maintenez Maj et cliquez sur une autre case. Les deux extrémités et les lignes sélectionnables entre elles suivent la case cible : la cocher sélectionne la plage ; la décocher la désélectionne. Les sélections existantes hors de cette plage sont conservées.
La plage suit l’ordre visible des lignes sur la page courante. Les en-têtes de groupe, les lignes repliées, les lignes désactivées et celles limitées à une sélection unique sont exclus. Le tri, les filtres, la pagination ou le repli d’un groupe peuvent modifier cet ordre ; le Maj-clic suivant se comporte alors comme un clic normal et définit un nouveau point de départ. Sans point de départ ou avec enableMultiRowSelection: false, Maj-clic reste un simple changement de case.
La sélection par intervalle concerne les cases du tableau et les cartes de la galerie. Les raccourcis décrits ci-dessous permettent de sélectionner tous les résultats sur plusieurs pages.
Flux de confirmation
copy et delete utilisent une boîte de dialogue de confirmation.
Comportement actuel :
L'utilisateur clique sur
CopyouDelete.La boîte de dialogue s'ouvre et stocke l'action en attente.
Les clics externes sont ignorés tant que la confirmation est ouverte.
Confirmexécute l'action en attente exactement une fois.La fermeture du menu suit le résultat du callback (
closeMenu).
Cela évite le cas précédent où un clic externe réinitialisait l'état pendant que la boîte de dialogue (portal) était ouverte.
Comportement déterministe des actions
edit: appelle immédiatementonBulkEditsi fourni ; sinon ouvre l’éditeur groupé du catalogue.export: appelle immédiatementonBulkExportsi fourni ; sinon, avectable.exportactivé (par défaut), ouvre l'écran d'export avec la sélection déjà choisie ; avectable.export: false, écrit immédiatement un CSV de la sélection.copy: confirmation toujours requise.delete: confirmation toujours requise.
Contrat des callbacks bulk
Structure de retour recommandée :
type BulkActionResult = {
success: boolean;
closeMenu: boolean;
clearSelection: boolean;
message?: string;
};Exemple (onBulkDelete)
onBulkDelete: async (rows) => {
const ids = rows.map((row) => String((row.original as { id: string }).id));
const response = await deleteMany(ids);
return {
success: response.success,
closeMenu: response.success,
clearSelection: response.success,
message: response.success
? `Deleted ${ids.length} rows`
: response.error ?? "Delete failed",
};
};Compatibilité legacy
Yayaw Table normalise encore les retours hérités des callbacks, mais le contrat explicite par objet est fortement recommandé pour un comportement prévisible.
Éditeur groupé du catalogue
En l'absence de onBulkEdit, si actions.bulkUpdate(ids, patch) existe, React et Vue ouvrent l'éditeur intégré du catalogue. Un callback onBulkEdit fourni reste prioritaire.
Commencez par Ajouter un champ, recherchez une propriété, puis saisissez sa nouvelle valeur dans son éditeur habituel. Seules les propriétés ajoutées apparaissent dans le formulaire. Le bouton de retrait exclut une propriété de la mise à jour sans modifier ses données. Effacer la valeur est proposé pour les champs facultatifs pris en charge uniquement lorsque leur schéma accepte la valeur vide. Les champs obligatoires ne peuvent pas être effacés ainsi.
Le bouton Appliquer à N lignes reste désactivé tant que les champs préparés ne
passent pas la validation. Après un succès partiel, son compteur correspond
uniquement aux cibles restantes. La présentation commune utilise un drawer à droite sur desktop et mobile ;
les boutons restent en dehors de la zone de défilement des champs.
Les callbacks onBulkEdit personnalisés et le mode JSON explicite de Vue
conservent leur comportement existant.
L'éditeur capture les identifiants à l'ouverture, initialise les valeurs communes aux lignes et n'envoie que les champs ajoutés. Les identités, horodatages, champs bulkEdit: false, lignes interdites et champs masqués ou désactivés pour une cible sont exclus. Des lignes résolvant des types de formulaire différents ne partagent pas un même éditeur. Modifier la sélection pendant l'édition ne change pas les cibles capturées.
context.bulkEdit contient ids, rows et les fields ajoutés. Les validations de champ et de collection imbriquée s'appliquent. Le schéma global de ligne est omis : les champs obligatoires non ajoutés n'ont pas à figurer dans un patch. Une transformation reçoit uniquement les champs ajoutés. Les valeurs explicites false, 0, "", [] et null sont conservées.
const bulkUpdate = async (ids, patch) => {
const failedIds = await updateProductsIndependently(ids, patch);
return failedIds.length
? { success: false, failedIds, error: "Certaines lignes n'ont pas été modifiées" }
: { success: true };
};failedIds doit être le sous-ensemble complet restant à modifier. Les succès quittent la sélection ; une nouvelle tentative cible uniquement les échecs et conserve le brouillon et les champs ajoutés. Sans failedIds, toutes les cibles restent présentes après un échec. Un compte rendu invalide ne vide jamais silencieusement les cibles. Ce résultat de persistance est distinct du contrat du callback de menu présenté ci-dessous.
Portée de la sélection et de l'export
Les deux éditions conservent les lignes sélectionnées entre pages et tailles de page. Désélectionner une ligne conserve les autres, même hors page. Changer la recherche, les filtres, le tri ou le regroupement efface la sélection. Tout sélectionner respecte les permissions et ignore les réponses obsolètes après un changement de requête ou de sélection. Utilisez des identifiants stables ou getRowId en pagination serveur ; les valeurs hors page restent celles du dernier chargement.
L'export groupé porte sur la sélection. Exporter (dans le menu Données) récupère toutes les lignes correspondant aux filtres et au tri capturés. Voici comment les utilisateurs choisissent quoi exporter : sélectionner des lignes, puis cliquer sur Exporter dans la barre d'actions de masse — avec table.export activé, cela ouvre l'écran d'export du menu Données avec « Sélection (n) » déjà choisi, et l'utilisateur peut toujours basculer vers « Toutes celles de la vue ». Le CSV intégré contient les colonnes de données visibles dans leur ordre d'affichage. onExport et onBulkExport restent prioritaires. Voir Écran d'export et l'intégration Query pour la pagination et le rafraîchissement.
Sélectionner sur plusieurs pages
Utilisez le parcours Administration avec editableActions. Sélectionnez deux produits, ajoutez seulement Stock dans l’éditeur groupé et appliquez 24 : noms et prix doivent rester inchangés.
Copiez cette configuration complète à côté de product-config.ts. Utilisez () => exampleConfig pour getTableConfig en React, ou :config="exampleConfig" en Vue.
Données de démonstration. Les modifications restent dans cet aperçu.
import { defineTableConfig } from "@/components/ui/yayaw-table/config/helpers";
import { productConfig } from "./product-config";
export const exampleConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
enableRowSelection: true,
enableMultiRowSelection: true,
preserveSelectionOnQuery: true,
allowEdit: true,
allowBulkEdit: true,
defaultPageSize: 2,
pageSizeOptions: [2, 10],
},
});Données de démonstration. Les modifications restent dans cet aperçu.
import { defineTableConfig } from "@/components/ui/yayaw-table-vue/config";
import { productConfig } from "./product-config";
export const exampleConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
enableRowSelection: true,
enableMultiRowSelection: true,
preserveSelectionOnQuery: true,
allowEdit: true,
allowBulkEdit: true,
defaultPageSize: 2,
pageSizeOptions: [2, 10],
},
});Proposer la sélection sans édition groupée
Gardez l’export de la sélection tout en désactivant les modifications et suppressions. Ce réglage convient à un écran de consultation.
Copiez cette configuration complète à côté de product-config.ts. Utilisez () => exampleConfig pour getTableConfig en React, ou :config="exampleConfig" en Vue.
Données de démonstration. Les modifications restent dans cet aperçu.
import { defineTableConfig } from "@/components/ui/yayaw-table/config/helpers";
import { productConfig } from "./product-config";
export const exampleConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
enableRowSelection: true,
enableMultiRowSelection: true,
bulkExport: true,
allowBulkEdit: false,
allowBulkDelete: false,
},
});Données de démonstration. Les modifications restent dans cet aperçu.
import { defineTableConfig } from "@/components/ui/yayaw-table-vue/config";
import { productConfig } from "./product-config";
export const exampleConfig = defineTableConfig({
...productConfig,
table: {
...productConfig.table,
enableRowSelection: true,
enableMultiRowSelection: true,
bulkExport: true,
allowBulkEdit: false,
allowBulkDelete: false,
},
});Sélection au clavier
Ctrl/Cmd+A sélectionne tous les éléments autorisés correspondant à la requête, y compris les pages serveur, sans sélection préalable. En galerie, Ctrl/Cmd-clic bascule un élément et Maj-clic étend l’intervalle visible sans ouvrir l’aperçu ni la fiche. Les cases du tableau conservent leur sélection par intervalle. Un nouvel ordre visible réinitialise l’ancre. Le Kanban conserve ses cases et participe à la sélection globale.
Le tableau actif reçoit les raccourcis. Un tableau visible unique les reçoit aussi si le focus est sur la page. Les champs, contenus éditables et fenêtres ouvertes gardent leur comportement natif ; les autres contrôles et tableaux masqués ne captent pas les raccourcis. Ctrl/Cmd+Z utilise le gestionnaire d’annulation de l’historique, y compris pour les éléments supprimés si l’application fournit cet historique.
Dupliquer la sélection
Ctrl/Cmd+D appelle l’action existante actions.duplicate(id) pour chaque élément sélectionné dans le tableau, la galerie ou le Kanban actif. Il faut table.allowDuplicate !== false et l’autorisation de table.canDuplicateRow pour tous les éléments sélectionnés. Les éditeurs de texte, dialogues et menus conservent leurs raccourcis natifs. Les répétitions de touche et demandes concurrentes sont ignorées.
Retournez { success: true, data: createdRecord } avec le nouvel identifiant pour sélectionner les copies après actualisation. Un échec arrête le lot, conserve les originaux non traités dans la sélection avec les copies réussies et affiche une erreur. Un lot entièrement réussi affiche une seule notification traduite, au singulier ou au pluriel. L’application gère la duplication, les identifiants uniques, les droits, le stockage et les quotas ; la bibliothèque ne recrée jamais un élément avec son ancien identifiant.
En React, passez getRowId={(row) => String(row.id)} (ou votre identifiant stable) pour que les copies sélectionnées et les sélections hors page utilisent la même identité que les lignes visibles.