Salta ai contenuti

Campi Personalizzati

Rebase genera campi modulo automaticamente in base ai tipi di proprietà. Per un comportamento personalizzato, puoi costruire i tuoi campi.

Un campo personalizzato è un componente React che riceve 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>
);
}
Prop Type Description
value T Valore attuale del campo
setValue (value: T) => void Aggiorna il valore del campo
error string Messaggio di errore di validazione
showError boolean Se visualizzare l’errore
isSubmitting boolean Il modulo è in fase di salvataggio
property Property La configurazione della proprietà
context FormContext Contesto completo del modulo con tutti i valori dell’entità
disabled boolean Il campo è di sola lettura
tableMode boolean Rendering all’interno del foglio di calcolo (modalità compatta)

Registra su una singola proprietà:

properties: {
brand_color: {
type: "string",
name: "Brand Color",
admin: {
Field: ColorPickerField
}
}
}

Quando il file della collection è letto anche dal server

Sezione intitolata “Quando il file della collection è letto anche dal server”

Nello scaffold predefinito, config/collections/ viene caricato sia dal pannello di amministrazione sia dal backend — il backend legge gli stessi file per ricavare schema e API. Un riferimento diretto al componente è sicuro solo se nessuna parte del server carica quel file, perché importare ColorPickerField importa anche React, il tuo CSS e tutto ciò che il componente porta con sé nel grafo dei moduli del server.

Indica invece il componente con un import lazy. Viene controllato dai tipi allo stesso modo e il backend non lo invoca mai:

// config/collections/products.ts
properties: {
brand_color: {
type: "string",
name: "Brand Color",
admin: {
Field: () => import("../../frontend/src/ColorPickerField"),
Preview: () => import("../../frontend/src/ColorPreview")
}
}
}

Il modulo deve avere un export default — il thunk risolve default, e un export solo con nome non renderizza nulla. Il pannello lo avvolge in React.lazy al primo render, quindi il componente diventa un chunk separato anziché parte del bundle iniziale.

Registra un tipo di campo riutilizzabile:

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>

Quindi usalo in qualsiasi collezione:

properties: {
color: {
type: "string",
name: "Color",
propertyConfig: "color_picker"
}
}

I campi personalizzati possono accedere a tutti i valori dell’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>With tax: ${priceWithTax.toFixed(2)}</p>
</div>
);
}

Quando si effettua il rendering all’interno della vista foglio di calcolo, i campi dovrebbero essere compatti. Controlla tableMode:

function MyField({ value, setValue, minimalistView }: FieldProps<StringProperty>) {
if (minimalistView) {
return <span onClick={() => { /* open editor */ }}>{value}</span>;
}
return (
<div>
<label>Full Editor</label>
<textarea value={value ?? ""} onChange={(e) => setValue(e.target.value)} />
</div>
);
}

Per il rendering personalizzato nella tabella (modalità non di modifica), usa il componente 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>
);
}
// Register it
properties: {
color: {
type: "string",
name: "Color",
admin: {
Field: ColorPickerField,
Preview: ColorPreview
}
}
}