Вопрос или проблема
Сообщество StackExchange,
Я создал пользовательский формат с использованием API форматов. Мне нужен способ получения списка форматов, используемых в currently выбранном блоке. По сути, это должно работать аналогично getActiveFormat( value, formatName )
. Основное отличие заключается в том, что эта функция получает только экземпляр формата выделенного текста. Мне нужен список каждого экземпляра моего пользовательского формата, так как пользовательские форматы будут иметь уникальные атрибуты, которые будут добавлены при применении пользовательского формата. Например, я хочу сделать следующее.
const currentBlock = wp.data.select('core/block-editor').getSelectedBlock()
const formats = getActiveFormats( currentBlock )
console.log(formats)
// Ожидается, что будет выведен текущий список всех экземпляров форматов в виде объектов
Если вы создавали функции раньше, это должно генерировать список аналогично свойству value.formats
, которое передается через редактирование. Было бы полезно любая помощь.
Дополнительный контекст
Ниже приведен пример того, как я добавляю новый формат. По сути, формат добавляет ссылку на запись, которая будет использоваться для вызова модального вида записи. Объект значения имеет свойство formats, которое содержит обновленный список форматов, используемых в блоке. Затем я использую render_block, чтобы вставить свой HTML модального окна в зависимости от того, какие записи указаны через формат. Если я смогу разобрать список экземпляров моего пользовательского формата в атрибут блока, это должно сработать. Проблема, с которой я сталкиваюсь, заключается в том, чтобы применить формат, а затем обновить атрибут блока с помощью функции onChange, которая передается в свойства редактирования.
import {
registerFormatType,
getActiveFormat,
getActiveFormats,
useAnchorRef
} from '@wordpress/rich-text';
import { default as ModalPopover } from './components/modal-popover';
const formatName="custom-format/modal-text-link";
function ModalEdit( props ) {
const {
name,
activeAttributes,
activeObjectAttributes,
value,
onChange,
contentRef,
} = props
// ...удалено для простоты
console.log( value.formats );
// возвращает текущий список всех форматов в этом блоке
return (
<>
<RichTextToolbarButton
icon={ <Icon size="36px" icon={ inbox } /> }
title="Модальная ссылка"
onClick={ openModal }
isActive={ isActive() }
/>
{ isOpen && (
<ModalPopover
name={ formatName }
value={ value }
onClose={ closeModal }
onChange={ ( ...args ) => onChange( ...args ) }
isFormat={ true }
anchorRef={ anchorRef }
changeAttribute={ changeAttribute }
/>
) }
</>
);
}
registerFormatType( formatName, {
title: 'Модальная текстовая ссылка',
tagName: 'a',
className: 'modal-text-link',
edit: ModalEdit,
} );
Посмотрите на пакет формата core link
Функция Edit()
, которая использует хук useLayoutEffect
, получает contentRef
в качестве параметра и прикрепляет, а затем удаляет обработчик событий, который может предоставить вам доступ к текущим форматам RichText как ‘children / childNodes’
Однако будьте осторожны, я новичок в js/react и не знаю, насколько затратными являются оба этих подхода.
function Edit({ isActive, value, onChange, contentRef }) {
useLayoutEffect(() => {
const editableContentElement = contentRef.current;
if (!editableContentElement) {
return;
}
console.log(editableContentElement);
}, [contentRef, isActive]);
// ...
return <SomeButton />;
}
Ответ или решение
Чтобы получить список форматов блока в редакторе Gutenberg WordPress, вы можете воспользоваться функцией getActiveFormats
, которая предназначена для извлечения всех активных форматов для данного блока.
Вот пример, как вы можете это сделать в вашем компоненте ModalEdit
:
import {
registerFormatType,
getActiveFormats,
} from '@wordpress/rich-text';
import { useSelect } from '@wordpress/data';
const formatName = "custom-format/modal-text-link";
function ModalEdit( props ) {
const {
value,
onChange,
} = props;
// Получаем список активных форматов блока
const currentBlock = useSelect(select => select('core/block-editor').getSelectedBlock(), []);
const formats = getActiveFormats(value);
console.log(formats); // Логируем активные форматы блока
// ... остальная логика компонента
return (
<>
{/* Ваши компоненты интерфейса, такие как кнопки и модальные окна */}
</>
);
}
registerFormatType( formatName, {
title: 'Modal Text Link',
tagName: 'a',
className: 'modal-text-link',
edit: ModalEdit,
} );
Объяснение кода:
-
Получение текущего блока: Используйте
useSelect
для извлечения текущего выбранного блока с помощьюselect('core/block-editor').getSelectedBlock()
. Это позволяет вам работать с состоянием редактора. -
Получение активных форматов: Используйте
getActiveFormats(value)
для получения всех активных форматов текста в переданном значении текста (в данном случае,value
). Этот вызов вернёт массив объектов форматов, которые активны для текущего блока. -
Логирование: Проверьте, какие форматы были применены, с помощью
console.log(formats)
. Это поможет вам отладить и убедиться, что форматы правильно извлекаются.
Дополнительные советы:
-
Поскольку вы упоминаете, что вы новичок в JavaScript и React, важно помнить, что использование хуков, таких как
useSelect
, является стандартной практикой в функциональных компонентах React. Они позволяют вам подключаться к состоянию и получать данные из Redux-подобного хранилища в Gutenberg. -
Если вам необходимо работать с атрибутами формата, вам может потребоваться дополнительно модифицировать логику работы с формами, чтобы убедиться, что при изменении форматов сохраняются изменения атрибутов.
В заключение:
Обратите внимание, что производительность вашего кода может зависеть от множества факторов, таких как сложность ведения состояния и количество активных форматов в каком-либо блоке. Однако, использование useSelect
и getActiveFormats
должно быть оптимизировано для случаев использования, как описано в вашем вопросе.