Автозаполнение Wordpress Gutenberg - сохранение атрибутов

Я хочу разработать настраиваемый блок, который позволит пользователю выбирать некоторую информацию из автозаполнения. Мне удалось создать компонент автозаполнения в функции редактирования.

Пользователь может выбрать элемент, но я не знаю, как обработать сохранение атрибута.

Я пытаюсь сохранить выбранный элемент как атрибут package_name. Я создал функцию onChange для компонента Autocomplete, но event.target.value не определен.

Вот мой код из block.js

const { __ } = wp.i18n; // Import __() from wp.i18n
const {  AlignmentToolbar,
        BlockControls,
        registerBlockType } = wp.blocks; 
const { RichText } = wp.editor;
const { Autocomplete, } =wp.components;


const MyAutocomplete = () => {
    const autocompleters = [
        {
            name: 'fruit',   
            triggerPrefix: '@',   
            options: [
                {  name: 'Apple', id: 1 },
                {  name: 'Orange', id: 2 },
                {  name: 'Grapes', id: 3 },
                {  name: 'test', id: 4 },
            ],

            getOptionLabel: option => (
                <span>
                  { option.name }
                </span>
            ),

            getOptionKeywords: option => [ option.name ],

            isOptionDisabled: option => option.name === 'Grapes',

            getOptionCompletion: option => (
                <abbr title={ option.name }>{ option.name }</abbr>
            ),
        }
    ];

    function onChangeAuto(newContent){
        console.log('autocompletexx '+newContent);
    }

    function onSelectAuto(event){
        console.log(event.target);
           console.log( event.target.value);
    }

    return (
        <div>
            <Autocomplete completers={ autocompleters }>
                { ( { isExpanded, listBoxId, activeId } ) => (
                    <div
                        contentEditable
                        suppressContentEditableWarning
                        aria-autocomplete="list"
                        aria-expanded={ isExpanded }
                        aria-owns={ listBoxId }
                        aria-activedescendant={ activeId }
                        onChange={onChangeAuto }
                        onSelect={onSelectAuto}

                    >
                    </div>
                ) }
            </Autocomplete>
            <p class="autocomplete_p">Type @ for triggering the autocomplete.</p>
        </div>
    );
};




registerBlockType( 'residence-gutenberg-block/membership-package-settings', {
    title: __( 'Residence - Membership Package Settings' ), // Block title.
    icon: 'shield', 
    category: 'common', 
    keywords: [
        __( 'membership-package-settings' ),
    ],
        attributes:{
            package_id:{
                type:'string',
                select:'p'
            },
            package_name:{
                type:'string',
            },
        },


    edit: function( props ) {

                const { attributes: {package_name}, className,setAttributes,isSelected } = props;               
        return (
            <div className={ props.className }>
                            <form>
                                <label className="wpresidence_editor_label">Current Package: {package_name}</label>
                                <MyAutocomplete></MyAutocomplete>
                             </form>

            </div>

        );
    },

    save: function( props ) {
              // Rendering in PHP
                return null;

    },
} );

person Crerem    schedule 23.08.2018    source источник


Ответы (1)


Передача onChange, onSelect элементу div не будет работать, потому что эти атрибуты применимы только к элементам поля формы (как input, select и т. Д.).

Я проверил документацию и исходный код и не нашел никаких подробностей или официальных подходов к решению этого дела.

Однако я вижу два возможных подхода для получения выбранного значения:

1. Использование автозаполнения onReplace prop

Заглянем в a>, я заметил, что обратный вызов onSelect вызывает onReplace prop с выбранной опцией в виде массива. Он может не подходить для всех случаев, но вы можете попробовать! Для вашего случая этого может хватить! Вы можете попробовать добавить свой обработчик в onReplace следующим образом:

<Autocomplete
  onReplace={ option => { console.log(option) } }
  completers={ autocompleters }>
  { ( { isExpanded, listBoxId, activeId } ) => (
    <div
      contentEditable
      suppressContentEditableWarning
      aria-autocomplete="list"
      aria-expanded={ isExpanded }
      aria-owns={ listBoxId }
      aria-activedescendant={ activeId }
    />
  ) }
</Autocomplete>

2. Прослушивайте <div /> изменений вручную.

Вы можете добавить onInput, onBlur слушателей к <div />, имея неконтролируемый реагирующий компонент div, и когда значение div изменяется, мы можем сохранить измененное значение в состоянии вашего родительского компонента.

Вот отличное обсуждение, в котором описывается этот метод: React.js: событие onChange для contentEditable

Хорошо, что уже есть плагин (на основе этого обсуждения), который может сделать это за вас: react- contenteditable.

Сначала вам нужно преобразовать ваш <MyAutocomplete /> компонент в состояние с полным состоянием (не функциональным), а затем:

import ContentEditable from 'react-contenteditable'

// Boilerplate ...

<Autocomplete completers={ autocompleters }>
  { ( { isExpanded, listBoxId, activeId } ) => (
    <ContentEditable
      html={this.state.html}
      onChange={this.handleChange}
      contentEditable
      suppressContentEditableWarning
      aria-autocomplete="list"
      aria-expanded={ isExpanded }
      aria-owns={ listBoxId }
      aria-activedescendant={ activeId }
    />
  ) }
</Autocomplete>

Заключение

Я удивлен, что в документации по автозаполнению нет подробностей об этом кейс. Думаю, это из-за следующего заявления (27.08.2018):

Gutenberg разрабатывается на GitHub, и сегодня вы можете попробовать раннюю бета-версию из репозитория плагинов. Однако имейте в виду, что он не полностью функциональный, функциональный или готовый к производству.

Однако один из обоих упомянутых выше подходов поможет вам, пока они не предоставят полный API для работы со своими компонентами.

Я бы посоветовал вам и дальше оборачивать <Autocomplete /> Wordpress своим собственным компонентом - чтобы легко реорганизовать код позже, когда они выпустят полный API.

Если у вас есть вопросы, не стесняйтесь комментировать ниже.

person Jordan Enev    schedule 27.08.2018
comment
Спасибо, что нашли время ответить. Даже если ответ не содержал точного ответа, информация и советы, которыми вы поделились, помогли мне найти решение. Спасибо еще раз. - person Crerem; 28.08.2018
comment
Добро пожаловать и рады помочь вам. Не могли бы вы поделиться подробностями здесь - как вы разрешили свое дело, и я включу их в ответ, чтобы помочь другим разработчикам. И тебе спасибо! :) - person Jordan Enev; 28.08.2018