Расширяемость Strapi особенно заметна в пользовательских полях: они позволяют создавать специализированные типы ввода под любые требования. В этом руководстве мы шаг за шагом рассмотрим процесс разработки кастомных полей — от базовой настройки до продвинутых сценариев.
Пользовательские поля существенно повышают удобство редактирования контента в Strapi, предоставляя тематические варианты ввода, что улучшает качество данных и ускоряет работу редакторов.
Пользовательские поля Strapi имеют архитектуру, похожую на плагин, и состоят из фронтенд- и бэкенд-частей. Понимание этой структуры необходимо, чтобы поле корректно интегрировалось в админку.
// Directory structure for a custom field
my-custom-field/
├── admin/
│ ├── components/
│ │ └── colorPicker.jsx // Frontend React component
├── fields/
│ │ └── colorPicker.js // Field configuration
│ └── index.js // Admin registration
├── server/
│ ├── register // Server-side registration
│ │ └── index.js
│ └── index.js/ // your export file
├── package.json
└── strapi-admin.js // admin entry point
└── strapi-server.js // Server entry point
Файл конфигурации описывает свойства поля: используемый компонент, доступные опции и правила валидации.
import { Discuss } from "@strapi/icons";
import pluginPk from "../../../package.json";
export default {
name: pluginPk.name,
pluginId: pluginPk.strapi.name,
type: "string",
icon: Discuss,
intlLabel: {
id:'{pluginPk.strapi.name}.{pluginPk.name}.field.label,
defaultMessage: "Comment"
},
intlDescription: {
id: '{pluginPk.strapi.name}.{pluginPk.name}.field.description,
defaultMessage: "Simple comment without any input. User as private field, and only in admin itself"
},
options: {
base: [
{
name: "options.comment",
description: "The comment",
defaultValue: "",
type: "textarea",
intlLabel: {
id: '{pluginPk.strapi.name}.{pluginPk.name}.field.label,
defaultMessage: "Comment"
}
},
{
name: "options.variant",
intlLabel: {
id: '{pluginPk.strapi.name}.{pluginPk.name}.field.variant.label,
defaultMessage: "Color variant"
},
type: "select",
value: "success",
defaultValue: "success",
options: [
{
key: "success",
value: "success",
metadatas: {
intlLabel: {
id: '{pluginPk.strapi.name}.{pluginPk.name}.field.variant.option.success.label,
defaultMessage: "Success"
}
}
},
{
key: "warning",
value: "warning",
metadatas: {
intlLabel: {
id: '{pluginPk.strapi.name}.{pluginPk.name}.field.variant.option.warning.label,
defaultMessage: "Warning"
}
}
},
{
key: "error",
defaultValue: "error",
value: "error",
metadatas: {
intlLabel: {
id: '{pluginPk.strapi.name}.{pluginPk.name}.field.variant.option.error.label,
defaultMessage: "Error"
}
}
}
],
},
],
advanced: [
{
sectionTitle: {
id: 'global.settings',
defaultMessage: 'Settings'
},
items: [
{
name: "private",
type: "checkbox",
defaultValue: true,
disabled: true,
intlLabel: {
id:'{pluginPk.strapi.name}.{pluginPk.name}.field.private.label',
defaultMessage: "Private Field",
},
intlDescription: {
id: '{pluginPk.strapi.name}.{pluginPk.name}.field.private.description',
defaultMessage: "This field is shown up in API response",
}
}
]
},
],
},
components: { Input: async () => import("../../components/comment") }
}
Фронтенд-компонент отвечает за отображение поля в админ-панели Strapi. Он создаётся на React и должен следовать гайдлайнам интерфейса Strapi, обеспечивая нужную функциональность.
import React from "react";
import { Box, Typography, DesignSystemProvider } from "@strapi/design-system";
import { Information, CrossCircle, MarkCircle } from "@strapi/icons";
const colors = {
success: {
background: "success200",
Icon: Information,
textColor: "neutral800",
},
warning: {
background: "warning200",
Icon: MarkCircle,
textColor: "neutral800",
},
error: {
background: "danger200",
Icon: CrossCircle,
textColor: "neutral800",
},
};
const CommentField = React.forwardRef((props, ref) => {
const { comment, variant } = props.attribute.options;
const { background, textColor, Icon } = colors[variant];
return (
<DesignSystemProvider>
<Box
background={background}
padding={4}
style={{ borderRadius: "8px", display: "flex", alignItems: "center" }}
ref={ref}
>
{Icon ? <Icon style={{ verticalAlign: "middle" }} /> : ""}
<Typography style={{ marginLeft: ".5rem" }} textColor={textColor}>
{comment}
</Typography>
</Box>
</DesignSystemProvider>
);
});
export default CommentField;
Чтобы Strapi увидел ваше поле, его нужно корректно зарегистрировать: добавить все необходимые файлы и описать, как админка должна подключать компонент.
"use strict";
import fields from "./fields";
export default {
register(app) {
for (const field of fields) {
app.customFields.register(field);
}
},
};
Чтобы Strapi распознал пользовательское поле, его необходимо зарегистрировать на сервере. Это включает создание файлов регистрации и описание поведения поля.
// server/register/index.js
"use strict";
const pluginPkg = require('../../package.json');
module.exports = ({ strapi }) => {
strapi.customFields.register({
name: pluginPkg.name,
plugin: pluginPkg.strapi.name,
type: "string",
});
strapi.customFields.register({
name:'tooltip-field',
plugin: pluginPkg.strapi.name,
type: "string",
})
strapi.customFields.register({
name:'tooltip-number-field',
plugin: 'superfields',
type: "integer",
})
strapi.customFields.register({
name:'tooltip-boolean-field',
plugin: 'superfields',
type: "boolean",
})
strapi.customFields.register({
name:'tooltip-enum-field',
plugin: 'superfields',
type: "string",
})
strapi.customFields.register({
name:'multi-select',
plugin: 'superfields',
type: "string",
})
strapi.customFields.register({
name:'tooltip-datetime-field',
plugin: 'superfields',
type: "date",
})
strapi.customFields.register({
name:'tooltip-color-picker',
plugin: 'superfields',
type: "string",
})
};
Чтобы Strapi распознал пользовательское поле, его необходимо зарегистрировать на сервере. Это включает создание файлов регистрации и описание поведения поля.
// server/register/index.js
"use strict";
const pluginPkg = require('../../package.json');
module.exports = ({ strapi }) => {
strapi.customFields.register({
name: pluginPkg.name,
plugin: pluginPkg.strapi.name,
type: "string",
});
};
Для корректной работы Strapi должен знать, как импортировать серверную регистрацию вашего поля, поэтому её нужно экспортировать из корневых файлов плагина.
// server/index.js
"use strict";
const register = require("./register");
module.exports = {
register,
};
//your-plugin/strapi-admin.js
"use strict";
import admin from "./admin";
export default admin;
--------------------------------------------------------------------------------------------------------------------------------------
//your-plugin/strapi-server.js
"use strict";
module.exports = require("./server");
Пользовательские поля в Strapi — идеальное сочетание гибкости для разработчиков и удобства для редакторов контента. Они помогают создавать интерфейсы под конкретные задачи, делая работу с контентом интуитивной и устойчивой к ошибкам.- Майя Джонсон, директор по UX в ContentFirst
Это исследование имеет несколько важных импликаций для профессионалов в этой области:
Пользовательские поля значительно расширяют возможности Strapi, позволяя создавать специализированные способы ввода под любые сценарии. Следуя описанным паттернам, вы сможете обогатить админ-панель интуитивными компонентами, которые повышают и удобство редактирования, и качество данных. Будь то небольшие улучшения или сложные структуры, кастомные поля дают ту гибкость, которая делает Strapi по-настоящему вашим.