
# Champs de formulaire

Le tableau `fields` d'un formulaire est une liste ordonnée de définitions de champs affichés de haut en bas. Chaque champ est l'un de cinq **types** (`kinds`), distingués par une propriété `kind`. Les champs liés à une table héritent de leur type et de leur validation d'une colonne de table ; les champs autonomes sont typés en ligne ; les champs de calcul, de section et de signature couvrent les valeurs calculées, les séparateurs et les signatures.

```yaml
forms:
  - id: 1
    name: signup
    title: Create your account
    submitTo: { table: users }
    fields:
      - { kind: table-field, column: email, required: true }
      - { kind: standalone, name: newsletter, inputType: checkbox, label: Subscribe to updates }
```

## Types de champs

| Type          | Description                                                                                                                                                              |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `table-field` | Lié à une colonne de `submitTo.table`. Le type, la validation et la persistance proviennent du schéma de table ; le formulaire ne surcharge que l'affichage.             |
| `standalone`  | Typé en ligne via `inputType` ; non persisté directement dans une colonne. À utiliser pour les formulaires qui n'acheminent que vers des automatisations ou le registre. |
| `calculation` | Valeur calculée en lecture seule dérivée d'autres champs via une formule `{{fieldName}}`. N'affiche aucune saisie.                                                       |
| `section`     | Séparateur visuel avec un titre et une description optionnels. N'affiche aucune saisie.                                                                                  |
| `signature`   | Capture une signature manuscrite ou saisie au clavier.                                                                                                                   |

## Propriétés communes des champs

Chaque type de champ portant une saisie (`table-field`, `standalone`, `calculation`, `signature`) partage une base commune.

| Propriété      | Description                                                                                                                            |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `label`        | Libellé affiché au contributeur. Prend en charge les clés i18n `$t:`.                                                                  |
| `placeholder`  | Texte indicatif affiché lorsque le champ est vide.                                                                                     |
| `helpText`     | Texte d'aide affiché sous le champ.                                                                                                    |
| `required`     | Booléen. Lorsque `true`, le champ doit avoir une valeur. Pour une obligation conditionnelle, utilisez `requiredWhen`.                  |
| `readOnly`     | Booléen. Affiche le champ en lecture seule.                                                                                            |
| `hidden`       | Booléen. Masque le champ de l'interface mais le soumet quand même (valeur côté serveur uniquement).                                    |
| `defaultValue` | Valeur littérale, ou une référence `$query.{name}` / `$user.{prop}` résolue au moment du rendu.                                        |
| `visibleWhen`  | Règle de visibilité conditionnelle. Voir [Logique conditionnelle](/fr/docs/form-conditional-logic).                                    |
| `requiredWhen` | Règle d'obligation conditionnelle (même forme que `visibleWhen`).                                                                      |
| `disabledWhen` | Règle de désactivation conditionnelle (même forme que `visibleWhen`).                                                                  |
| `permissions`  | Permission `read` par champ. Lorsque le rôle demandeur est exclu, la valeur est masquée des exports admin et du détail par soumission. |

## Champs liés à une table

Un `kind: table-field` référence une `column` sur la `submitTo.table` du formulaire. Le type de champ, la validation et la persistance proviennent tous du schéma de table — le formulaire ne fournit que les aspects d'affichage plus, pour les colonnes de pièce jointe, les options de téléversement.

| Propriété     | Description                                                                          |
| ------------- | ------------------------------------------------------------------------------------ |
| `column`      | Nom de la colonne sur `submitTo.table`. Obligatoire.                                 |
| `accept`      | Types MIME ou extensions séparés par des virgules pour les colonnes de pièce jointe. |
| `maxFileSize` | Taille maximale (octets) par fichier téléversé (colonnes de pièce jointe).           |
| `maxFiles`    | Nombre maximal de fichiers pour les colonnes `multiple-attachments`.                 |
| `dropZone`    | Affiche une zone de glisser-déposer à côté du sélecteur de fichiers.                 |

```yaml
fields:
  - kind: table-field
    column: subject
    label: What can we help with?
    placeholder: Briefly describe the issue
  - kind: table-field
    column: priority
    helpText: Urgent issues are triaged first
```

Les colonnes de pièce jointe (`single-attachment`, `multiple-attachments`) affichent automatiquement une saisie de fichier. Voir [Téléversements de fichiers](/fr/docs/form-file-uploads) pour le pipeline de téléversement et la liaison au bucket.

## Champs autonomes

Un champ `kind: standalone` est typé en ligne via `inputType` et n'est pas écrit directement dans une colonne de table. Il est idéal pour les formulaires qui acheminent vers une automatisation ou vivent uniquement dans le registre de soumissions.

| Propriété     | Description                                                                                         |
| ------------- | --------------------------------------------------------------------------------------------------- |
| `name`        | Nom de champ unique au sein du formulaire (`^[a-zA-Z][a-zA-Z0-9_-]*`, ≤64 caractères). Obligatoire. |
| `inputType`   | Type de contrôle (voir ci-dessous). Obligatoire.                                                    |
| `options`     | Choix `{ value, label }` pour `select` / `multi-select` / `radio`.                                  |
| `accept`      | Types MIME acceptés pour la saisie `attachment`.                                                    |
| `maxFiles`    | Nombre maximal de fichiers pour la saisie `attachment`.                                             |
| `maxFileSize` | Taille maximale (octets) par fichier téléversé.                                                     |
| `dropZone`    | Affiche une zone de glisser-déposer à côté du sélecteur de fichiers.                                |

**Valeurs `inputType` disponibles :** `short-text`, `long-text`, `email`, `url`, `phone`, `number`, `date`, `datetime`, `select`, `multi-select`, `checkbox`, `radio`, `rating`, `attachment`.

```yaml
fields:
  - kind: standalone
    name: rating
    inputType: rating
    label: How was your experience?
    required: true
  - kind: standalone
    name: source
    inputType: select
    label: How did you hear about us?
    options:
      - { value: search, label: Search engine }
      - { value: referral, label: Referral }
      - { value: social, label: Social media }
```

## Champs de calcul, de section et de signature

| Type          | Propriétés clés                                                                                                                               |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `calculation` | `name`, `formula` (référence d'autres champs via `{{name}}`), `format` optionnel (`number` / `currency` / `percent` / `text`). Lecture seule. |
| `section`     | `heading`, `description` optionnels, et une règle `visibleWhen` pour toute la section. N'affiche aucune saisie.                               |
| `signature`   | `name`. Capture une signature manuscrite ou saisie au clavier.                                                                                |

```yaml
fields:
  - { kind: standalone, name: quantity, inputType: number, label: Quantity }
  - { kind: standalone, name: unit_price, inputType: number, label: Unit price }
  - kind: calculation
    name: total
    label: Total
    formula: '{{quantity}} * {{unit_price}}'
    format: currency
```

## Préremplissage

Le mappage `prefill` de premier niveau initialise les valeurs des champs au moment du rendu. Les clés sont des noms de champs de formulaire ; les valeurs sont soit une valeur littérale par défaut, soit une référence :

| Référence        | Se résout en                                                                                                                         |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `$query.{name}`  | Un paramètre de chaîne de requête d'URL (par ex. `$query.utm_source`).                                                               |
| `$user.{prop}`   | Une propriété de l'utilisateur authentifié (par ex. `$user.email`). Silencieusement ignoré sur les formulaires publics sans session. |
| `$parent.{path}` | Un champ de l'enregistrement parent — valide uniquement pour les formulaires de relation en ligne (voir ci-dessous).                 |

```yaml
forms:
  - id: 1
    name: lead-capture
    title: Request a demo
    submitTo: { table: leads }
    prefill:
      utm_source: $query.utm_source
      utm_campaign: $query.utm_campaign
    fields:
      - { kind: table-field, column: email, required: true }
      - { kind: standalone, name: utm_source, inputType: short-text, hidden: true }
      - { kind: standalone, name: utm_campaign, inputType: short-text, hidden: true }
```

:::callout
**Deux façons de définir une valeur par défaut.** Le `defaultValue` par champ accepte les références `$query` / `$user` en ligne, tandis que le mappage `prefill` de premier niveau garde le câblage de préremplissage au même endroit. Sur un formulaire public (`access.require: all`), un `defaultValue: $user.*` par champ est rejeté au moment de la validation — utilisez le `prefill` de premier niveau (qui tolère une résolution `$user` vide) ou exigez l'authentification.
:::

## Création de relation en ligne

Lorsqu'un formulaire est intégré dans la page de détail d'un enregistrement parent (par ex. un bouton « + Nouveau ticket » sur une page Projet), la source de préremplissage `$parent.{path}` relie automatiquement le nouvel enfant à son parent. Cela se configure sur le contrôle de formulaire de page via `inlinePrefill`.

| Propriété     | Description                                                                                                                                    |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `prefill`     | Mappage nom-de-champ → source-de-préremplissage (même union `$query` / `$user` / `$parent`).                                                   |
| `lockPrefill` | Lorsque `true`, les champs préremplis sont masqués et ne peuvent pas être surchargés (toujours validés côté serveur). Vaut `false` par défaut. |

```yaml
forms:
  - id: 1
    name: new-ticket
    submitTo: { table: tickets }
    fields:
      - { kind: table-field, column: title, required: true }
      - { kind: table-field, column: project_id }
      - { kind: table-field, column: reporter_id }

pages:
  - id: 1
    name: project-detail
    path: /portal/projects/:id
    components:
      - type: form
        formRef: new-ticket
        inlinePrefill:
          prefill:
            project_id: $parent.id # locked to the current project
            reporter_id: $user.id
          lockPrefill: true
```

À la soumission, le moteur revalide l'existence du parent pour se prémunir contre les références `$parent` obsolètes. Les colonnes de relation simple et multiple sont toutes deux prises en charge.

## Pages associées

- [Présentation des formulaires](/fr/docs/forms-overview) — métadonnées de formulaire, cibles de soumission, contrôle d'accès.
- [Logique conditionnelle](/fr/docs/form-conditional-logic) — `visibleWhen` / `requiredWhen` / `disabledWhen`.
- [Formulaires multi-étapes](/fr/docs/form-multi-step) — distribuer les champs sur plusieurs étapes.
- [Téléversements de fichiers](/fr/docs/form-file-uploads) — options de saisie de pièce jointe et liaison au bucket.
- [Champs relationnels](/fr/docs/relational-fields) — les colonnes de relation ciblées par `$parent`.
- [Contrôles de formulaire](/fr/docs/form-controls) — le composant de page qui héberge `formRef` + `inlinePrefill`.
