Вопрос или проблема
Итак, у меня есть свой пользовательский блок, и он имеет InnerBlocks, который принимает любой блок. По умолчанию используется один абзацный блок.
wp.blocks.registerBlockType('accordion/child', {
apiVersion: 2,
title: 'Accordion Child',
category: 'design',
parent: [ "accordion/child" ],
attributes: {
title: {
type: 'string',
default: 'This is an accordion'
},
},
edit({ attributes, setAttributes }) {
const { title } = attributes;
const { createElement, Fragment } = wp.element;
const { PanelBody, TextareaControl } = wp.components;
const { InnerBlocks, InspectorControls } = wp.blockEditor;
let blockProps = wp.blockEditor.useBlockProps();
return createElement(Fragment, {},
createElement(InspectorControls, null,
createElement(PanelBody, { title: 'Settings' },
createElement(TextareaControl, {
label: 'Title',
value: title,
onChange: function (newTitle) {
setAttributes({ 'title': newTitle });
},
})
),
),
createElement('div',
{ ...blockProps },
createElement('div', {className:'accordion-child-content'},
createElement('div', {
className: 'accordion-child-title',
},
title
),
createElement(InnerBlocks,
{template: ["core/paragraph",{content:'This is the accordion content'}],
templateLock: false
}),
),
)
);
},
save: function ({ attributes }) {
const { createElement } = wp.element;
const { InnerBlocks } = wp.blockEditor;
const { title } = attributes;
return createElement('div',{className: 'accordion-child'},
createElement('div', {className: 'accordion-child-title',tabIndex: 0},
title
),
createElement('div', {className: 'accordion-child-content'},
createElement(InnerBlocks.Content)
)
);
}
});
Добавляется один или несколько блоков, и они сохраняются нормально. На фронтэнде они отображаются так, как и ожидалось. Но когда я перезагружаю редактор, он возвращается к одному абзацному блоку по умолчанию.
Как сделать, чтобы редактор показывал сохраненные блоки?
Ответ или решение
Проблема, с которой вы столкнулись при использовании InnerBlocks в вашем кастомном блоке WordPress, связана с тем, что добавленные дочерние блоки не сохраняются должным образом в редакторе после перезагрузки страницы. Это распространённая проблема, связанная с внутренними механизмами сохранения и восстановления состояний блоков в редакторе Gutenberg.
Причины проблемы
-
Неправильное использование атрибута
InnerBlocks
: После перезагрузки редактора, кажется, что блоки сбрасываются к шаблонному значению, потому что содержимое блока не сохраняется корректно. -
Атрибут
template
иtemplateLock
: Темплейты применяются каждый раз при загрузке блока в редакторе. Если сохранённые данные не учитываются, это может быть причиной проблемы.
Решение проблемы
-
Проверка правильности сохранения данных: Убедитесь в том, что редактор корректно сохраняет данные в
post_content
, и они корректно извлекаются при загрузке редактора. -
Использование
InnerBlocks
иInnerBlocks.Content
: Убедитесь, чтоInnerBlocks.Content
корректно извлекается в функцииsave
. Это может влиять на восстановление внутреннего состояния блоков в редакторе. -
Устранение коллизий в шаблоне блоков (
template
):- Убедитесь, что
template
иtemplateLock
не конфликтуют с содержимым, которое должно был загружено из сохранённого состояния. Подумайте об удалении или настройкиtemplate
таким образом, чтобы он не вмешивался в процесс загрузки сохранённых данных.
- Убедитесь, что
-
Правильное использование
useBlockProps
:useBlockProps
может быть неправильно применён, если не передавать все необходимые параметры. Убедитесь, что все атрибуты и их состояния корректно передаются и извлекаются в блоке.
-
Проверка на совместимость с API:
- Убедитесь, что вы используете правильную версию API (в вашем случае — версия 2), и что все функции и их параметры корректно соответствуют используемым API.
Пример корректного использования InnerBlocks
Если проблема сохраняется, рассмотрите рефакторинг вашего кода, основываясь на следующих шагах:
edit({ attributes, setAttributes }) {
const { title } = attributes;
const blockProps = wp.blockEditor.useBlockProps();
return (
<Fragment>
<InspectorControls>
<PanelBody title="Настройки">
<TextareaControl
label="Заголовок"
value={title}
onChange={(newTitle) => setAttributes({ title: newTitle })}
/>
</PanelBody>
</InspectorControls>
<div {...blockProps}>
<div className="accordion-child-content">
<div className="accordion-child-title">{title}</div>
<InnerBlocks
template={[["core/paragraph", { content: "Это контент аккордеона" }]]}
templateLock={false}
/>
</div>
</div>
</Fragment>
);
},
save({ attributes }) {
const { title } = attributes;
const blockProps = wp.blockEditor.useBlockProps.save();
return (
<div className="accordion-child" {...blockProps}>
<div className="accordion-child-title" tabIndex={0}>{title}</div>
<div className="accordion-child-content">
<InnerBlocks.Content />
</div>
</div>
);
}
Убедитесь, что ваш код соответствует актуальным стандартам блоковой реализации в WordPress, что поможет избежать подобных проблем.
Заключение
Следуя этим рекомендациям, вы сможете корректно внедрить InnerBlocks в ваш кастомный блок и добиться его корректной работы как в редакторе, так и на фронтенде. Главное, внимательно следите за атрибутами и используемыми API, чтобы избежать ошибок в будущем.