Yayaw
Documentation
Modifier et agir

Champs collection

Modifier des tableaux avec identités stables, champs imbriqués et validation.

Un champ collection conserve un tableau dans le formulaire parent. Il permet d’ajouter, modifier, supprimer et réordonner des éléments en ligne ou dans une boîte de dialogue.

Exemple de configuration

Partez du démarrage React ou du démarrage Vue. Le fichier suivant complète leur catalogue de produits. Passez cette configuration via getTableConfig en React ou config en Vue.

order-form.ts
import type { FormConfig } from "@/components/ui/yayaw-table/components/forms/types";
import { customers, orderSchema } from "../shared/orders";
import { customerConfig } from "./order-config";
import { renderProductSelect } from "./product-select";

export const orderForm: FormConfig = {
  id: "orders",
  title: "Edit order",
  presentation: "modal",
  width: "64rem",
  schema: orderSchema,
  fields: [
    { name: "reference", label: "Reference", type: "text", bulkEdit: false },
    {
      name: "customerId",
      label: "Customer",
      type: "tablePicker",
      tablePicker: {
        tableType: "customers",
        config: customerConfig,
        data: customers,
        getRowId: (row) => String(row.id),
        multiple: false,
        syncUrl: false,
        maxHeight: "18rem",
      },
    },
    {
      name: "lines",
      label: "Order lines",
      type: "collection",
      collectionMode: "dialog",
      addLabel: "Add line",
      getItemKey: (line) => String(line.id),
      createItem: () => ({
        id: crypto.randomUUID(),
        productId: "",
        quantity: 1,
        allocations: [],
      }),
      columns: [
        { id: "productId", header: "Product" },
        { id: "quantity", header: "Quantity" },
      ],
      validateItem: (line) =>
        Number(line.quantity) > 0 && line.productId
          ? []
          : ["Choose a product and a positive quantity."],
      validateItems: (lines) =>
        lines.length ? [] : ["Add at least one line."],
      itemFields: [
        {
          name: "productId",
          label: "Product",
          type: "custom",
          renderField: renderProductSelect,
        },
        {
          name: "quantity",
          label: "Quantity",
          type: "number",
          min: 1,
          step: 1,
        },
        {
          name: "allocations",
          label: "Warehouse allocations",
          type: "collection",
          collectionMode: "inline",
          getItemKey: (allocation) => String(allocation.id),
          createItem: () => ({
            id: crypto.randomUUID(),
            warehouse: "",
            quantity: 1,
          }),
          itemFields: [
            { name: "warehouse", label: "Warehouse", type: "text" },
            { name: "quantity", label: "Quantity", type: "number", min: 1 },
          ],
        },
      ],
    },
  ],
};
order-form.ts
import type { FormConfig } from "@/components/ui/yayaw-table-vue/types";
import { customers, orderSchema } from "../shared/orders";
import { products } from "../shared/products";
import { customerConfig } from "./order-config";

export const orderForm: FormConfig = {
  id: "orders",
  title: "Edit order",
  presentation: "modal",
  width: "64rem",
  schema: orderSchema,
  fields: [
    { name: "reference", label: "Reference", type: "text", bulkEdit: false },
    {
      name: "customerId",
      label: "Customer",
      type: "tablePicker",
      tablePicker: {
        tableType: "customers",
        config: customerConfig,
        data: customers,
        getRowId: (row) => String(row.id),
        multiple: false,
        syncUrl: false,
        maxHeight: "18rem",
      },
    },
    {
      name: "lines",
      label: "Order lines",
      type: "collection",
      collectionMode: "dialog",
      addLabel: "Add line",
      getItemKey: (line) => String(line.id),
      createItem: () => ({
        id: crypto.randomUUID(),
        productId: "",
        quantity: 1,
        allocations: [],
      }),
      columns: [
        { id: "productId", header: "Product" },
        { id: "quantity", header: "Quantity" },
      ],
      validateItem: (line) =>
        Number(line.quantity) > 0 && line.productId
          ? []
          : ["Choose a product and a positive quantity."],
      validateItems: (lines) =>
        lines.length ? [] : ["Add at least one line."],
      itemFields: [
        {
          name: "productId",
          label: "Product",
          type: "select",
          options: products.map((product) => ({
            value: product.id,
            label: product.name,
          })),
        },
        {
          name: "quantity",
          label: "Quantity",
          type: "number",
          min: 1,
          step: 1,
        },
        {
          name: "allocations",
          label: "Warehouse allocations",
          type: "collection",
          collectionMode: "inline",
          getItemKey: (allocation) => String(allocation.id),
          createItem: () => ({
            id: crypto.randomUUID(),
            warehouse: "",
            quantity: 1,
          }),
          itemFields: [
            { name: "warehouse", label: "Warehouse", type: "text" },
            { name: "quantity", label: "Quantity", type: "number", min: 1 },
          ],
        },
      ],
    },
  ],
};

Identité stable des éléments

Générez un identifiant dans createItem, puis utilisez-le dans getItemKey. L’index change lors d’un déplacement. createActions peut proposer plusieurs modèles d’éléments. columns définit leur résumé ; itemFields définit l’éditeur. Utilisez renderItemForm pour un éditeur métier personnalisé.

Valider à chaque niveau

validateItem vérifie un élément, validateItems la collection et le schéma du formulaire le document soumis. Les itemFields peuvent contenir une autre collection. Dans la recette commande, les lignes contiennent des allocations par entrepôt. La soumission enregistre la valeur imbriquée complète ; le tableau ne définit pas votre schéma relationnel.

Tester l’annulation

Ouvrez un élément, modifiez-le puis annulez : la valeur parent doit rester intacte. Réordonnez deux éléments et vérifiez que leurs identifiants les suivent. Testez une collection vide, un élément imbriqué invalide et un échec de soumission parent.

Essayer dans la page

Ouvrez la commande existante, puis ajoutez, réordonnez ou retirez ses lignes avant l’enregistrement.

Agrandir ↗

Données de démonstration. Les modifications restent dans cet aperçu.

Agrandir ↗

Données de démonstration. Les modifications restent dans cet aperçu.