Добавьте пользовательский атрибут данных к каждому блоку ядра Gutenberg

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

Я добавляю два пользовательских атрибута к основным блокам Гутенберга — data-delay и data-duration. Я хочу добавить эти атрибуты для управления анимацией в моем пользовательском шаблоне.

Я написал этот JS код в block-extension.js:

(function(wp) {
    const { addFilter } = wp.hooks;
    const { createHigherOrderComponent } = wp.compose;
    const { Fragment } = wp.element;
    const { InspectorControls } = wp.blockEditor;
    const { PanelBody, TextControl } = wp.components;

    // Добавьте новые атрибуты к блокам
    const addCustomAttributes = (settings, name) => {
        if (typeof settings.attributes !== 'undefined') {
            settings.attributes = Object.assign(settings.attributes, {
                dataDelay: {
                    type: 'string',
                    default: '0',
                },
                dataDuration: {
                    type: 'string',
                    default: '0',
                },
            });
        }
        return settings;
    };

    // Добавьте элементы управления для новых атрибутов
    const withCustomControls = createHigherOrderComponent((BlockEdit) => {
        return (props) => {
            if (props.isSelected) {
                return wp.element.createElement(
                    Fragment,
                    null,
                    wp.element.createElement(BlockEdit, props),
                    wp.element.createElement(
                        InspectorControls,
                        null,
                        wp.element.createElement(
                            PanelBody,
                            { title: 'Пользовательские атрибуты', initialOpen: true },
                            wp.element.createElement(TextControl, {
                                label: 'Data Delay',
                                value: props.attributes.dataDelay,
                                onChange: function(newVal) {
                                    props.setAttributes({ dataDelay: String(newVal) });
                                },
                            }),
                            wp.element.createElement(TextControl, {
                                label: 'Data Duration',
                                value: props.attributes.dataDuration,
                                onChange: function(newVal) {
                                    props.setAttributes({ dataDuration: String(newVal) });
                                },
                            })
                        )
                    )
                );
            }
            return wp.element.createElement(BlockEdit, props);
        };
    }, 'withCustomControls');

    // Добавьте атрибуты к HTML-оберткам блока
    const addCustomProps = (saveElementProps, blockType, attributes) => {
        if (attributes.dataDelay) {
            saveElementProps['data-delay'] = attributes.dataDelay;
        }
        if (attributes.dataDuration) {
            saveElementProps['data-duration'] = attributes.dataDuration;
        }
        return saveElementProps;
    };

    // Примените фильтры Gutenberg
    addFilter('blocks.registerBlockType', 'luxuryconcept/add-custom-attributes', addCustomAttributes);
    addFilter('editor.BlockEdit', 'luxuryconcept/with-custom-controls', withCustomControls);
    addFilter('blocks.getSaveContent.extraProps', 'luxuryconcept/add-custom-props', addCustomProps);
})(window.wp);

и PHP код в functions.php:

function my_custom_gutenberg_extension() {
    wp_enqueue_script(
        'block-extension',
        get_template_directory_uri() . '/assets/js/block-extension.js', 
        array('wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-compose', 'wp-hooks'),
        filemtime(get_template_directory() . '/assets/js/block-extension.js'),
        true
    );
}
add_action('enqueue_block_editor_assets', 'my_custom_gutenberg_extension');

Я получил это для всех блоков:

пользовательские атрибуты

Но когда я добавляю блок в редактор Гутенберга, я получаю эти JS ошибки для каждого блока:

js ошибка

Я думаю, что причина в том, что оригинальное содержание отличается от того, у которого добавлены два атрибута data, но я не знаю, как с этим справиться.

Спасибо

–ИЗМЕНЕНИЕ–

Итак, мне нужно удалить

addFilter('blocks.getSaveContent.extraProps', 'luxuryconcept/add-custom-props', addCustomProps);

и добавить этот PHP код, чтобы получить атрибуты:

function theme_custom_add_custom_attributes($block_content, $block) {
    // Проверьте, установлен ли атрибут и не пуст ли он
    $data_delay = get_field('data-delay', $block['id']);
    $data_duration = get_field('data-duration', $block['id']);

    // Добавьте атрибуты к блоку только если они установлены
    if ($data_delay && !empty($data_delay)) {
        $block_content = str_replace('<div', '<div data-delay="' . esc_attr($data_delay) . '"', $block_content);
    }
    if ($data_duration && !empty($data_duration)) {
        $block_content = str_replace('<div', '<div data-duration="' . esc_attr($data_duration) . '"', $block_content);
    }

    return $block_content;
}
add_filter('render_block', 'theme_custom_add_custom_attributes', 10, 2);

Но я не знаю, как сохранить их в PHP.

Я нашел решение:

  1. Я убрал addFilter('blocks.getSaveContent.extraProps', 'luxuryconcept/add-custom-props', addCustomProps);, как и рекомендовал @TomJNowell.
  2. Я добавил add_filter('render_block', 'theme_custom_add_custom_attributes', 10, 2); PHP код в functions.php:

Итак, вот весь рабочий код:

JS:

/**
 * 
 * Расширяет функциональность основных блоков Гутенберга
 * 
 * @description Добавляет атрибуты data-delay и data-duration ко всем основным блокам Гутенберга
 * @package luxuryconcept
 * @author Stefano Fattori <[email protected]>
 * @copyright Stefano Fattori ©2024
 * @url www.stefanofattori.it
 * 
 */

(function(wp) {
    const { addFilter } = wp.hooks;
    const { createHigherOrderComponent } = wp.compose;
    const { Fragment } = wp.element;
    const { InspectorControls } = wp.blockEditor;
    const { PanelBody, TextControl } = wp.components;

    // Добавьте новые атрибуты к блокам
    const addCustomAttributes = (settings, name) => {
        if (typeof settings.attributes !== 'undefined') {
            settings.attributes = Object.assign({}, settings.attributes, {
                dataDelay: {
                    type: 'string',
                    default: '0',
                },
                dataDuration: {
                    type: 'string',
                    default: '0',
                },
            });
        }
        return settings;
    };

    // Добавьте элементы управления для новых атрибутов
    const withCustomControls = createHigherOrderComponent((BlockEdit) => {
        return (props) => {
            if (props.isSelected) {
                return wp.element.createElement(
                    Fragment,
                    null,
                    wp.element.createElement(BlockEdit, props),
                    wp.element.createElement(
                        InspectorControls,
                        null,
                        wp.element.createElement(
                            PanelBody,
                            { title: 'Пользовательские атрибуты', initialOpen: true },
                            wp.element.createElement(TextControl, {
                                label: 'Data Delay',
                                value: props.attributes.dataDelay,
                                onChange: function(newVal) {
                                    props.setAttributes({ dataDelay: String(newVal) });
                                },
                            }),
                            wp.element.createElement(TextControl, {
                                label: 'Data Duration',
                                value: props.attributes.dataDuration,
                                onChange: function(newVal) {
                                    props.setAttributes({ dataDuration: String(newVal) });
                                },
                            })
                        )
                    )
                );
            }
            return wp.element.createElement(BlockEdit, props);
        };
    }, 'withCustomControls');

    // Примените фильтры Gutenberg
    addFilter('blocks.registerBlockType', 'luxuryconcept/add-custom-attributes', addCustomAttributes);
    addFilter('editor.BlockEdit', 'luxuryconcept/with-custom-controls', withCustomControls);

})(window.wp);

PHP:

/**
 * Добавляет пользовательские атрибуты к основным блокам Гутенберга (Frontend)
 * 
 * @see /assets/js/block-extension.js
 * 
 * @param mixed $block_content
 * @param mixed $block
 * @return mixed
 */
function theme_custom_add_custom_attributes($block_content, $block) {
    // Проверьте, есть ли пользовательские атрибуты 'dataDelay' и 'dataDuration'
    if ( isset($block['attrs']['dataDelay']) && !empty($block['attrs']['dataDelay']) ) {
        $block_content = add_custom_attribute($block_content, 'data-delay', $block['attrs']['dataDelay']);
    }
    if ( isset($block['attrs']['dataDuration']) && !empty($block['attrs']['dataDuration']) ) {
        $block_content = add_custom_attribute($block_content, 'data-duration', $block['attrs']['dataDuration']);
    }

    return $block_content;
}

/**
 * Функция для добавления атрибутов данных к HTML блокам
 * 
 * @param mixed $block_content
 * @param mixed $attribute_name
 * @param mixed $attribute_value
 * @return mixed
 * 
 * @since 1.5.5
 */
function add_custom_attribute($block_content, $attribute_name, $attribute_value) {
    // Найдите первый HTML-тег в содержимом блока
    $pos = strpos($block_content, '>');

    if ($pos !== false) {
        // Вставьте пользовательский атрибут после первого HTML-тега
        $block_content = substr_replace($block_content, ' ' . $attribute_name . '="' . esc_attr($attribute_value) . '"', $pos, 0);
    }

    return $block_content;
}
add_filter('render_block', 'theme_custom_add_custom_attributes', 10, 2);

Спасибо!

Это прекрасно сработало с моей стороны. Спасибо @stefano !!!

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

Чтобы добавить пользовательские атрибуты data-delay и data-duration ко всем основным блокам Gutenberg и избежать ошибок JavaScript, связанных с несовпадением оригинального содержимого блока, вы можете следовать приведенному ниже решению. Это решение включает модификацию JavaScript и PHP кода.

JavaScript код (block-extension.js)

/**
 * 
 * Расширяет функциональность основных блоков Gutenberg
 * 
 * @description Добавляет атрибуты data-delay и data-duration ко всем основным блокам Gutenberg
 * @package luxuryconcept
 * @author Stefano Fattori
 */

(function(wp) {
    const { addFilter } = wp.hooks;
    const { createHigherOrderComponent } = wp.compose;
    const { Fragment } = wp.element;
    const { InspectorControls } = wp.blockEditor;
    const { PanelBody, TextControl } = wp.components;

    // Добавляем новые атрибуты к блокам
    const addCustomAttributes = (settings, name) => {
        if (typeof settings.attributes !== 'undefined') {
            settings.attributes = Object.assign({}, settings.attributes, {
                dataDelay: {
                    type: 'string',
                    default: '0',
                },
                dataDuration: {
                    type: 'string',
                    default: '0',
                },
            });
        }
        return settings;
    };

    // Добавляем управляющие элементы для новых атрибутов
    const withCustomControls = createHigherOrderComponent((BlockEdit) => {
        return (props) => {
            if (props.isSelected) {
                return wp.element.createElement(
                    Fragment,
                    null,
                    wp.element.createElement(BlockEdit, props),
                    wp.element.createElement(
                        InspectorControls,
                        null,
                        wp.element.createElement(
                            PanelBody,
                            { title: 'Custom Attributes', initialOpen: true },
                            wp.element.createElement(TextControl, {
                                label: 'Data Delay',
                                value: props.attributes.dataDelay,
                                onChange: function(newVal) {
                                    props.setAttributes({ dataDelay: String(newVal) });
                                },
                            }),
                            wp.element.createElement(TextControl, {
                                label: 'Data Duration',
                                value: props.attributes.dataDuration,
                                onChange: function(newVal) {
                                    props.setAttributes({ dataDuration: String(newVal) });
                                },
                            })
                        )
                    )
                );
            }
            return wp.element.createElement(BlockEdit, props);
        };
    }, 'withCustomControls');

    // Применяем фильтры Gutenberg
    addFilter('blocks.registerBlockType', 'luxuryconcept/add-custom-attributes', addCustomAttributes);
    addFilter('editor.BlockEdit', 'luxuryconcept/with-custom-controls', withCustomControls);

})(window.wp);

PHP код (functions.php)

/**
 * Добавляет пользовательские атрибуты к блоку Gutenberg (FrontEnd)
 * 
 * @param mixed $block_content
 * @param mixed $block
 * @return mixed
 */
function theme_custom_add_custom_attributes($block_content, $block) {
    // Проверяем наличие пользовательских атрибутов 'dataDelay' и 'dataDuration'
    if ( isset($block['attrs']['dataDelay']) && !empty($block['attrs']['dataDelay']) ) {
        $block_content = add_custom_attribute($block_content, 'data-delay', $block['attrs']['dataDelay']);
    }
    if ( isset($block['attrs']['dataDuration']) && !empty($block['attrs']['dataDuration']) ) {
        $block_content = add_custom_attribute($block_content, 'data-duration', $block['attrs']['dataDuration']);
    }

    return $block_content;
}

/**
 * Функция для добавления пользовательских атрибутов к HTML блокам
 * 
 * @param mixed $block_content
 * @param mixed $attribute_name
 * @param mixed $attribute_value
 * @return mixed
 */
function add_custom_attribute($block_content, $attribute_name, $attribute_value) {
    // Находим первое HTML тег в содержимом блока
    $pos = strpos($block_content, '>');
    if ($pos !== false) {
        // Вставляем пользовательский атрибут после первого HTML тега
        $block_content = substr_replace($block_content, ' ' . esc_attr($attribute_name) . '="' . esc_attr($attribute_value) . '"', $pos, 0);
    }
    return $block_content;
}

add_filter('render_block', 'theme_custom_add_custom_attributes', 10, 2);

Объяснение изменений:

  1. Удаление лишних фильтров: Убедитесь, что не используете addFilter('blocks.getSaveContent.extraProps', ...), чтобы избежать конфликтов с оригинальным содержимым блока.

  2. Добавление атрибутов на серверной стороне: Определяем атрибуты data-delay и data-duration с помощью фильтра render_block, который позволяет изменять HTML-код блока перед его выводом на экран.

  3. Функция для добавления атрибутов: Функция add_custom_attribute ищет первое HTML-тег в содержимом блока и добавляет к нему пользовательские атрибуты.

Заключение

С помощью приведенного выше решения вы сможете добавить кастомные данные атрибуты к основным блокам Gutenberg без возникновения ошибок JavaScript. Теперь ваш код будет работать корректно и вы сможете управлять анимацией через указанные атрибуты.

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

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