# Custom fields
Custom fields are plugins that extend Strapi’s capabilities by adding new fields to content-types. Once created or installed, custom fields can be used in the Content-Types Builder and Content Manager just like built-in fields.
The present reference documentation is intended to custom fields creators. It describes how custom fields work and can be created from a developer point of view, describing the APIs available to build a new custom field. The user guide describes how to install and use custom fields from Strapi's admin panel.
🤓 Prefer to learn by building?
If you'd rather directly jump to a concrete example, see the Creating a color custom field guide page for step-by-step instructions on how to build your first custom field from scratch.
Custom fields are a specific type of Strapi plugins that include both a back-end (or server) part and a front-end (or admin panel) part. Both parts should be registered for the custom fields to be available and usable in Strapi's admin panel:
strapi.customFields.register
registers the server part of a custom field instrapi-server.js
app.customFields.register
registers the admin panel part of a custom field instrapi-admin.js
Once registered, custom fields can be used in models's schema.json
. Custom fields' attributes should declare their type
as customField
and use the customField
property to mention the registered custom field to use (see model's custom fields documentation).
# Registering a custom field on the server
On the server part, Strapi needs to be aware of all custom fields to ensure that an attribute using a custom field is valid. To achieve this, the strapi.customFields
object exposes a register()
method on the Strapi
instance.
strapi.customFields.register()
registers a custom field on the server during the plugin's server register lifecycle and should pass an object with the following parameters:
Parameter | Description | Type |
---|---|---|
name | The name of the custom field | String |
plugin (optional) | The name of the plugin creating the custom fields | String |
type | The existing, built-in Strapi data type the custom field will use (e.g. string, number, JSON — see models documentation for the full list). | String |
TypeScript shapes to register a custom field on the server:
The following Strapi API is exposed to help you register a custom field on the server:
interface CustomFieldServerOptions {
// The name of the custom field
name: string;
// The name of the plugin creating the custom field
plugin?: string;
// The existing Strapi data type the custom field will use
type: string;
}
strapi.customFields.register(
options: CustomFieldServerOptions | CustomFieldServerOptions[]
);
Example: Registering an example "checkbox" custom field on the server:
// path: ./src/plugins/my-custom-field-plugin/strapi-server.js
module.exports = {
register({ strapi }) {
strapi.customFields.register({
name: 'checkbox',
plugin: 'my-custom-field-plugin',
type: 'boolean',
});
},
};
# Registering a custom field in the admin panel
On the admin panel part, the custom field should be described to be available in the Content-Type Builder and the Content Manager. To achieve this, the app.customFields
exposes a register
method on the StrapiApp
instance.
app.customFields.register()
registers a custom field in the admin panel during the plugin's admin bootstrap lifecycle and should pass an object (or an array of objects) with the following parameters:
Parameter | Description | Type |
---|---|---|
name | The name of the custom field | String |
pluginId (optional) | The name of the plugin creating the custom field | String |
type | The existing Strapi data type the custom field will use | String |
intlLabel | The translation for the name | IntlObject |
intlDescription | The translation for the description | IntlObject |
icon (optional) | The icon for the custom field | React.ComponentType |
components | The components needed to display the custom field in the Content Manager (see components) | |
options (optional) | The settings to extend in the Content-Type Builder (see options) | Object |
✏️ NOTE
Relations, components or dynamic zones can't be used as a custom field's type
parameter.
TypeScript shapes to register a custom field in the admin panel:
The following Strapi APIs are exposed to help you register a custom field on the server:
// You can also pass an array of objects to register several custom fields at once
app.customFields.register(
options: CustomFieldAdminOptions | CustomFieldAdminOptions[]
);
interface CustomFieldAdminOptions {
// The name of the custom field
name: string;
// The name of the plugin creating the custom field
pluginId?: string;
// The existing Strapi data type the custom field will use
type: string;
// The translation for the name
intlLabel: IntlObject;
// The translation for the description
intlDescription: IntlObject;
// The icon for the custom field
icon?: React.ComponentType;
// The components needed to display the custom field in the Content Manager
components: {
// Input component for the Edit view
Input: () => Promise<{ default: React.ReactComponent }>;
// Read only component for the List view
View: () => Promise<{ default: React.ReactComponent }>;
};
// The settings to extend in the Content-Type Builder
options?: {
base: CTBFormSection[];
advanced: CTBFormSection[];
validator: (args) => object;
}
}
interface IntlObject {
id: string;
defaultMessage: string;
}
interface CTBFormSection {
sectionTitle: IntlObject;
items: CTBFormInput[];
}
interface CTBFormInput {
name: string;
description: InltObject;
type: string;
intlLabel: IntlObject;
}
Example: Registering an example "checkbox" custom field in the admin panel:
// strapi-admin.js
register(app) {
app.customFields.register({
name: "checkbox",
pluginId: "checkbox",
type: "boolean",
intlLabel: {
id: "checkbox.label",
defaultMessage: "Checked",
},
intlDescription: {
id: "checkbox.description",
defaultMessage: "Click to toggle the checkbox",
}
icon: CheckboxIcon,
components: {
Input: async () => import(/* webpackChunkName: "input-component" */ "./Input"),
View: async () => import(/* webpackChunkName: "view-component" */ "./View"),
},
});
}
# Components
The components
parameter used in app.customFields.register()
should include 2 components:
- an
Input
component to define the React component to use in the Content Manager's edit view, - and a
View
component View to define a read-only component used in the Content Manager's list view.
Both components could be declared as promises returning a React component imported from another file (e.g. Input: async () => import(/* webpackChunkName: "input-component" */ "./Input"
).
# Options
app.customFields.register()
can pass additional options to be used for the base and advanced settings tabs of the Content-Type Builder. The options
object accepts the following parameters:
Options parameter | Description | Type |
---|---|---|
base | Settings available in the Base settings tab of the Content-Type Builder | Object or Object[] |
advanced | Settings available in the Advanced settings tab of the Content-Type Builder | Object or Object[] |
validator | Validator function returning an object (useful to sanitize input, for instance) | Function |
Both base
and advanced
settings accept:
- a
sectionTitle
(as an ReactIntlObject
) - and a list of
items
as an array of objects, each object containing the following parameters:
Items parameter | Description | Type |
---|---|---|
intlLabel | Label for the setting item, in the React Intl format | Object |
name | Name of the setting to be used, in the following format: options.<setting-name> | String |
type | ? | String |
value | ? | String |
metadatas | ? | Object |
✏️ NOTE
When extending a custom field’s base and advanced forms in the Content-type Builder, it is not yet possible to import custom input components.
TypeScript shapes to declare options:
The following types and shapes are used to describe the options
when registering a custom field in the admin panel:
options?: {
base: CTBFormSection[];
advanced: CTBFormSection[];
validator: (args) => object;
}
interface IntlObject {
id: string;
defaultMessage: string;
}
interface CTBFormSection {
sectionTitle: IntlObject;
items: CTBFormInput[];
}
interface CTBFormInput {
name: string;
description: InltObject;
type: string;
intlLabel: IntlObject;
}
Example of options passed when registering a custom field in the admin panel:
(TODO)