Как динамически добавить шаблон в Innerblock?

Вопрос или проблема

Я пытаюсь динамически добавить шаблон в мой InnerBlock, для этого я попробовал следующий код:

const edit = props => {
    var { 
        className, 
        attributes,
        setAttributes,
        clientId
    } = props;
    var { templateList } = attributes;

    const ALLOWBLOCKS = ['ss-gutenberg-block/accordion-child'];
    
    setAttributes({ blockId: clientId });
   
    return (
        <Fragment>
            <div className={className}>
                <div className = { "accordionParentWrapper" }>
                    <InnerBlocks
                        template = { templateList }
                        allowedBlocks = { ALLOWBLOCKS }
                        templateLock = { "true" }
                    />
                    <span 
                        className = { "dashicons dashicons-plus editor-icons" }
                        onClick = {() => setAttributes({ templateList: [...templateList, ['ss-gutenberg-block/accordion-child'] ] })}
                    ></span>
                    <span 
                        className = { "dashicons dashicons-minus editor-icons" }
                        onClick = {() => setAttributes({ templateList: templateList.length ? templateList.splice(-1, 1) : templateList })}
                    ></span>
                </div>
            </div>
        </Fragment>
    );
}

и атрибут templateList по умолчанию состоит из [['ss-gutenberg-block/accordion-child']]. Я хочу динамически добавлять или удалять дочерний блок из Innerblock. Кнопки работают нормально и добавляют и удаляют в массиве. Но визуально блоки не добавляются и не удаляются.

Это не так, как работают шаблоны.

Шаблон — это начальная структура блоков, отправная точка.

Изменение шаблона ничего не даст, потому что оригинальный шаблон был использован для создания блоков, и эти блоки уже были созданы. Подумайте, если бы это работало так, как вы думаете, добавление или удаление из шаблона стерло бы весь контент, и ваш контент был бы стерт при загрузке поста.

Что вы сделали, так это попытались создать пользовательский аппендер для блоков, так что вместо изобретения этой функции заново вы должны использовать свойство блокового аппендера и API. Шаблоны не подходят для того, что вы пытаетесь сделать.

Вкратце: если вы хотите создать пользовательский аппендер/вставщик блоков, используйте пользовательский вставщик/аппендер блоков, не пытайтесь делать шаблоны динамическими, они не являются и не могут быть динамическими, это не так, как работают шаблоны.

Чтобы динамически добавлять или удалять шаблоны в компоненте InnerBlocks, вам нужно правильно управлять состоянием списка шаблонов и убедиться, что изменения в списке шаблонов вызывают перерисовку компонента InnerBlocks.

const { InnerBlocks } = wp.editor;
const { Fragment } = wp.element;

const edit = props => {
    const { className, attributes, setAttributes } = props;
    const { templateList } = attributes;

    const ALLOWBLOCKS = ['ss-gutenberg-block/accordion-child'];

    const addTemplate = () => {
        const newTemplateList = [...templateList, ['ss-gutenberg-block/accordion-child']];
        setAttributes({ templateList: newTemplateList });
    };

    const removeTemplate = () => {
        const newTemplateList = [...templateList];
        newTemplateList.pop(); // Удалить последний шаблон
        setAttributes({ templateList: newTemplateList });
    };

    return (
        <div className={className}>
            <div className="accordionParentWrapper">
                <InnerBlocks
                    template={templateList}
                    allowedBlocks={ALLOWBLOCKS}
                    templateLock="all"
                />
                <span
                    className="dashicons dashicons-plus editor-icons"
                    onClick={addTemplate}
                ></span>
                <span
                    className="dashicons dashicons-minus editor-icons"
                    onClick={removeTemplate}
                ></span>
            </div>
        </div>
    );
};

export default edit;

созданы отдельные функции addTemplate и removeTemplate для управления добавлением и удалением шаблонов из списка шаблонов, после этого внутри функции создается новый массив newTemplateList на основе текущего templateList и добавляется или удаляется шаблон из него, затем вызываем setAttributes для обновления атрибута templateList новым массивом.

Ответ или решение

Вопрос о динамическом добавлении шаблонов в компонент InnerBlocks в среде разработки WordPress является частым и требует правильного понимания работы с шаблонами и атрибутами блоков. Давайте разберем эту тему подробно.

Изменение шаблона в InnerBlocks

В оригинальном коде, предоставленном в вопросе, проблема заключается в неправильном применении шаблонов для динамического изменения содержимого блоков. Шаблоны в Gutenberg служат для заданий начальной структуры блоков и не предназначены для динамического обновления после создания блоков.

Почему шаблоны неподходящи для динамических изменений

Использование шаблонов для динамических изменений в InnerBlocks контрпродуктивно, так как:

  • Шаблоны определяют структуру блоков на этапе их создания и не обновляются динамически.
  • Попытка изменения шаблона не повлияет на уже существующие блоки. Вместо этого, такие изменения могут привести к неочевидным ошибкам, например, потеря данных, если бы шаблоны действительно обновлялись.

Альтернативное решение

Чтобы динамически добавлять или удалять блоки, необходимо использовать механизмы, встроенные в Gutenberg, такие как кастомные методы добавления блоков. Рассмотрим, как это можно сделать:

const { InnerBlocks } = wp.blockEditor; // wp.editor был заменен на wp.blockEditor в актуальных версиях
const { Fragment } = wp.element;

const edit = props => {
    const { className, attributes, setAttributes } = props;
    const { templateList } = attributes;

    const ALLOWBLOCKS = ['ss-gutenberg-block/accordion-child'];

    // Функция добавляет новый блок в список
    const addTemplate = () => {
        const newTemplateList = [...templateList, ['ss-gutenberg-block/accordion-child']];
        setAttributes({ templateList: newTemplateList });
    };

    // Функция удаляет последний блок из списка
    const removeTemplate = () => {
        const newTemplateList = [...templateList];
        newTemplateList.pop(); // Удаляем последний элемент
        setAttributes({ templateList: newTemplateList });
    };

    return (
        <div className={className}>
            <div className="accordionParentWrapper">
                <InnerBlocks
                    template={templateList}
                    allowedBlocks={ALLOWBLOCKS}
                    templateLock="all"
                />
                <span
                    className="dashicons dashicons-plus editor-icons"
                    onClick={addTemplate}
                ></span>
                <span
                    className="dashicons dashicons-minus editor-icons"
                    onClick={removeTemplate}
                ></span>
            </div>
        </div>
    );
};

export default edit;

Практические рекомендации

  1. Используйте встроенные средства добавления блоков: Внутри компонента InnerBlocks можно реализовать свои контролы для добавления и удаления блоков, которые будут сохранять структуру данных, но не нарушать подачи Gutenberg.

  2. Работайте с состоянием компонента: Используйте setAttributes для управления состоянием и атрибутами, это обеспечит реактивность и позволит компонентам обновляться адекватно.

  3. Учитесь у лучших примеров: Изучайте существующие примеры блоков и их реализации, чтобы видеть, как опытные разработчики решают подобные задачи.

Следуя этим рекомендациям и приведенному коду, можно более эффективно управлять шаблонами и динамически добавлять или удалять блоки в редакторе WordPress.

Оцените материал
Добавить комментарий

Капча загружается...