Вопрос или проблема
Я разрабатываю некоторые пользовательские блоки в новом редакторе Gutenberg, и мне трудно понять, как использовать некоторые встроенные компоненты, в основном компоненты Draggable.
Что я хотел бы достичь, так это список элементов (скажем, много li
в ul
) и я хочу, чтобы их можно было упорядочивать с помощью функции перетаскивания.
Вот мой код:
import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import { Draggable, Dashicon } from '@wordpress/components';
import './style.scss';
import './editor.scss';
registerBlockType( 'namespace/my-custom-block',
{
title: __( 'Пользовательский блок', 'namespace'),
description: __( 'Описание пользовательского блока', 'namespace' ),
category: 'common',
icon: 'clipboard',
keywords: [
__( 'список', 'namespace' ),
__( 'элемент', 'namespace' ),
__( 'порядок', 'namespace' )
],
supports: {
html: false,
multiple: false,
},
attributes: {
items: {
type: 'array',
default: [ 'Один' ,'Два' ,'Три' ,'Четыре' ,'Пять' ,'Шесть' ,'Семь' ,'Восемь' ,'Девять' ,'Десять' ]
}
},
edit: props => {
return (
<ul>
{ props.attributes.items.map( (itemLabel, id) => (
<li id={ `li_${id}` } draggable>
<Draggable
elementId={ `li_${id}` }
transferData={ {} }>
{
({ onDraggableStart, onDraggableEnd }) => (
<Dashicon
icon="move"
onDragStart={ onDraggableStart }
onDragEnd={ onDraggableEnd }
draggable
/>
)
}
</Draggable>
{ itemLabel }
</li>
))
}
</ul>
)
},
save: () => {
// Вернуть null, чтобы он рендерился на сервере
return null;
}
}
)
На стороне сервера он правильно отображается, но элементы не поддаются перетаскиванию
К сожалению, справочник разработчика Gutenberg не дает много информации
https://wordpress.org/gutenberg/handbook/designers-developers/developers/components/draggable/ и я не вижу, как это сделать.
Спасибо и всего хорошего
Если вам нужно сделать что-то перетаскиваемое, что появляется внутри вашего блока в основной области контента, то вам следует использовать дочерние блоки для реализации этого, и компонент <InnerBlocks/>
. Затем вы можете заставить внутренние блоки быть только вашим новым типом дочернего блока.
Например, у нас может быть блок kuuak/my-custom-block
, и каждый перетаскиваемый элемент будет блоком kuuak/my-custom-block-item
. Затем вы можете использовать это, чтобы позволить элементам вставляться и сортироваться, но только блок вашего элемента, ничего другого:
const ALLOWED_BLOCKS = [ 'kuuak/my-custom-block-item' ];
//...
<InnerBlocks allowedBlocks={ ALLOWED_BLOCKS } />;
Вы также можете заставить так, чтобы блоки элементов не использовались нигде больше, когда их регистрируете:
"parent": [ "kuuak/my-custom-block" ],
Этот паттерн используется во многих блоках ядра WordPress, например, в блоке колонок, который может содержать только блоки “колонка”, новые галерейные блоки, которые действуют как контейнеры для отдельных изображений, каруселей и т.д.
Дополнительное чтение о вложенных/внутренних блоках: https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/nested-blocks-inner-blocks/
Используйте react-sortable-hoc
Draggable не имеет достаточной документации, и у меня не было времени углубляться в это.
Но вышеприведенное подходит вам.
Я использовал его для создания боковой панели Entry Content/Primary Sidebar – использовалась для переупорядочивания контента/боковой панели моей темы!
Ответ или решение
Создание перетаскиваемых элементов в кастомных блоках Гутенберга: Пошаговое руководство
Разработка кастомных блоков в редакторе Гутенберг предоставляет мощные возможности для управления контентом. Однако работа с компонентами перетаскивания может вызывать затруднения, особенно если документация недостаточно полна. В этом руководстве мы рассмотрим, как создать упорядочиваемый список элементов (li
) внутри блока (ul
), используя дополнительный блок для каждого элемента списка.
Проблема
Ваш код корректно отображает элементы на сервере, однако функция перетаскивания не работает. Проблема заключается в том, что элементы, которые нужно перетаскивать, не могут быть реализованы напрямую через компонент Draggable
, поскольку он требует более сложной логики управления состоянием.
Подход с использованием InnerBlocks
Для достижения желаемого поведения рекомендуется использовать внутренние блоки (InnerBlocks
). Это позволит вам создать родительский блок, который будет содержать ваши элементы в качестве дочерних блоков.
Вот шаги, которые необходимо выполнить:
-
Создание родительского блока:
Начнем с регистрации вашего кастомного блока, который будет содержать внутренние блоки.
import { registerBlockType } from '@wordpress/blocks'; import { InnerBlocks } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; registerBlockType('namespace/my-custom-block', { title: __('Custom List Block', 'namespace'), icon: 'list-view', category: 'common', supports: { html: false, }, edit: () => { const ALLOWED_BLOCKS = ['namespace/my-custom-item']; return ( <div> <InnerBlocks allowedBlocks={ALLOWED_BLOCKS} /> </div> ); }, save: () => { return <InnerBlocks.Content />; } });
-
Создание дочернего блока для элементов списка:
Теперь создайте новый блок для каждого элемента списка, который будет перетаскиваемым.
registerBlockType('namespace/my-custom-item', { title: __('List Item', 'namespace'), parent: 'namespace/my-custom-block', edit: (props) => { return ( <div className="list-item"> <textarea value={props.attributes.content} onChange={(e) => props.setAttributes({ content: e.target.value })} /> </div> ); }, save: () => { return <div className="list-item">{content}</div>; }, attributes: { content: { type: 'string', default: 'New item', }, }, });
-
Использование библиотеки для сортировки:
В качестве альтернативы встроенным компонентам, вы можете использовать библиотеку, такую как
react-sortable-hoc
для реализации функции перетаскивания. Пример использования:import SortableContainer from 'react-sortable-hoc'; const SortableList = SortableContainer(({ items }) => { return ( <ul> {items.map((value, index) => ( <SortableItem key={`item-${index}`} index={index} value={value} /> ))} </ul> ); }); const SortableItem = SortableElement(({ value }) => <li>{value}</li>); const onSortEnd = ({ oldIndex, newIndex }) => { // управление порядком элементов после завершения перетаскивания };
Заключение
Использование InnerBlocks
для организации ваших элементов и дополнительных библиотек для перетаскивания значительно упрощает вашу задачу. Это решение позволит вам создавать интерактивные и удобные для пользователя блоки в редакторе Гутенберг.
Однако интеграция сторонних библиотек требует дополнительной работы по управлению состоянием и обновлению UI. В этом контексте следует оценить и документы, которые предоставляют библиотеки, поскольку они могут облегчить реализацию необходимых функций.
Таким образом, создание перетаскиваемых элементов внутри Гутенберга — это не только реализация функционала, но и возможность улучшить UX вашего сайта через реализацию интуитивно понятного интерфейса.