Champs personnalisés
Rebase génère automatiquement des champs de formulaire basés sur les types de propriétés. Pour un comportement personnalisé, vous pouvez créer vos propres champs.
Créer un champ personnalisé
Section intitulée « Créer un champ personnalisé »Un champ personnalisé est un composant React qui reçoit des FieldProps :
import type { FieldProps } from "@rebasepro/cms";import type { StringProperty, NumberProperty } from "@rebasepro/types";
function ColorPickerField({ value, setValue, error, showError }: FieldProps<StringProperty>) { return ( <div> <input type="color" value={value ?? "#000000"} onChange={(e) => setValue(e.target.value)} /> {showError && error && <span className="text-red-500">{error}</span>} </div> );}FieldProps
Section intitulée « FieldProps »| Propriété | Type | Description |
|---|---|---|
value |
T |
Valeur actuelle du champ |
setValue |
(value: T) => void |
Mettre à jour la valeur du champ |
error |
string |
Message d’erreur de validation |
showError |
boolean |
Indique si l’erreur doit être affichée |
isSubmitting |
boolean |
Le formulaire est en cours d’enregistrement |
property |
Property |
La configuration de la propriété |
context |
FormContext |
Contexte complet du formulaire avec toutes les valeurs de l’entité |
disabled |
boolean |
Le champ est en lecture seule |
tableMode |
boolean |
Rendu à l’intérieur de la feuille de calcul (mode compact) |
Enregistrer un champ personnalisé
Section intitulée « Enregistrer un champ personnalisé »Par propriété
Section intitulée « Par propriété »Enregistrer sur une seule propriété :
properties: { brand_color: { type: "string", name: "Brand Color", admin: { Field: ColorPickerField } }}Quand le fichier de collection est aussi lu par le serveur
Section intitulée « Quand le fichier de collection est aussi lu par le serveur »Dans le scaffold par défaut, config/collections/ est chargé à la fois par le panneau d’administration et par le backend — le backend lit les mêmes fichiers pour en déduire le schéma et l’API. Une référence directe au composant n’est sûre que si rien côté serveur ne charge ce fichier, car importer ColorPickerField importe aussi React, votre CSS et tout ce que le composant entraîne dans le graphe de modules du serveur.
Désignez plutôt le composant par un import différé. Il est typé de la même manière et le backend ne l’appelle jamais :
// config/collections/products.tsproperties: { brand_color: { type: "string", name: "Brand Color", admin: { Field: () => import("../../frontend/src/ColorPickerField"), Preview: () => import("../../frontend/src/ColorPreview") } }}Le module doit avoir un export par défaut — le thunk résout default, et un export uniquement nommé n’affiche rien. Le panneau l’enveloppe dans React.lazy au premier rendu : le composant forme donc son propre chunk au lieu d’alourdir le bundle initial.
Configuration globale des propriétés
Section intitulée « Configuration globale des propriétés »Enregistrer un type de champ réutilisable :
const colorPropertyConfig: PropertyConfig = { key: "color_picker", name: "Color Picker", property: { type: "string", admin: { Field: ColorPickerField } }};
// Register globally — keyed by the config's `key`<Rebase propertyConfigs={{ color_picker: colorPropertyConfig }}>…</Rebase>Utilisez-le ensuite dans n’importe quelle collection :
properties: { color: { type: "string", name: "Color", propertyConfig: "color_picker" }}Accéder au contexte du formulaire
Section intitulée « Accéder au contexte du formulaire »Les champs personnalisés peuvent accéder à toutes les valeurs de l’entité :
function PriceWithTaxField({ value, setValue, context }: FieldProps<NumberProperty>) { const taxRate = Number(context.values.tax_rate ?? 0.1); const priceWithTax = value ? value * (1 + taxRate) : 0;
return ( <div> <input type="number" value={value ?? 0} onChange={(e) => setValue(Number(e.target.value))} /> <p>Avec taxe : ${priceWithTax.toFixed(2)}</p> </div> );}Mode Tableau
Section intitulée « Mode Tableau »Lors du rendu dans la vue feuille de calcul, les champs doivent être compacts. Vérifiez tableMode :
function MyField({ value, setValue, minimalistView }: FieldProps<StringProperty>) { if (minimalistView) { return <span onClick={() => { /* open editor */ }}>{value}</span>; }
return ( <div> <label>Éditeur complet</label> <textarea value={value ?? ""} onChange={(e) => setValue(e.target.value)} /> </div> );}Aperçus personnalisés
Section intitulée « Aperçus personnalisés »Pour un rendu personnalisé dans le tableau (mode non-édition), utilisez le composant Preview :
function ColorPreview({ value }: { value: string }) { return ( <div style={{ display: "flex", alignItems: "center", gap: 8 }}> <div style={{ width: 24, height: 24, borderRadius: 4, backgroundColor: value }} /> <span>{value}</span> </div> );}
// Enregistrer le composantproperties: { color: { type: "string", name: "Color", admin: { Field: ColorPickerField, Preview: ColorPreview } }}Prochaines étapes
Section intitulée « Prochaines étapes »- Vues d’entité — Onglets personnalisés dans l’éditeur d’entité
- Actions d’entité — Boutons d’action personnalisés
- Colonnes supplémentaires — Colonnes de tableau calculées
