Автозаполнение Wordpress Gutenberg, автозаполнение не завершено - PullRequest
0 голосов
/ 23 февраля 2020

Я пытаюсь создать блок Гутенберга с автоматическим завершением, но когда я пишу в расширенном тексте "post: xx", ничего не происходит, никаких ошибок

Для этого примера я черпал вдохновение у пользователя Autocompleter из Wp

Я также попробовал этого провайдера: https://github.com/WordPress/gutenberg/tree/master/packages/components/src/autocomplete#usage

Спасибо за вашу помощь

Зарегистрируйте мой блок

    registerBlockType('acmarche-gutenberg/bottin', {
....
edit:MyAutoComplete
...
}

Мой автозаполнение компонента

class MyAutoComplete extends Component {

    constructor() {
        super(...arguments);
        //   console.log(this.props);
    }

    setContent(newContent) {
        // console.log(newContent);
        //  setAttributes({content: newContent});
    };

    render() {
        return (
            <div key="editable">
                <Autocomplete completers={[jfAutocompleter()]}>
                    {({isExpanded, listBoxId, activeId}) => (
                        <RichText
                            onChange={(nextContent) => {
                                this.setContent(nextContent);
                            }}
                            placeholder="add text"
                            aria-autocomplete="list"
                            aria-expanded={isExpanded}
                            aria-owns={listBoxId}
                            aria-activedescendant={activeId}
                        >
                        </RichText>
                    )}
                </Autocomplete>
                <p>Type ~ for triggering the autocomplete.</p>
            </div>
        );
    }
}

Мой автозаполнение

function jfAutocompleter() {

    const getOptions = (search) => {
        let payload = '';
        if (search) {
            payload = '?search=' + encodeURIComponent(search);
        }
        return wp.apiRequest({path: '/wp/v2/users' + payload}).then((users) => {
            return users.map((user) => {
                return {
                    value: user,
                    label: [
                        <img key="avatar" className="blocks-autocompleters__user-avatar" alt=""
                             src={user.avatar_urls[24]}/>,
                        <span key="name" className="blocks-autocompleters__user-name">{user.name}zz</span>,
                        <span key="slug" className="blocks-autocompleters__user-slug">{user.slug}pp</span>,
                    ],
                    keywords: [user.slug, user.name],
                };
            });
        });
    };

    const allowNode = () => {
        return true;
    };

    const onSelect = (user) => {
        return ('post:' + user.slug);
    };

    return {
        className: 'blocks-autocompleters__user',
        triggerPrefix: 'post:',
        getOptions,
        allowNode,
        onSelect,
        isDebounced: true,
    };
}

1 Ответ

0 голосов
/ 02 марта 2020

Я думаю, что нашел способ обойти это с помощью wp.hooks.addFilter на RichText

Вот мое решение

блок. js

import {registerBlockType} from '@wordpress/blocks';
import apiFetch from '@wordpress/api-fetch';
import ServerSideRender from '@wordpress/server-side-render';
import {Disabled} from '@wordpress/components';
import {PanelBody, ToggleControl} from '@wordpress/components';
import {InspectorControls, PlainText, RichText} from '@wordpress/block-editor';
import {withState} from '@wordpress/compose';
import {addFilter} from '@wordpress/hooks';

registerBlockType('acmarche-block/bottin', {
    title: 'Bottin',
    description: 'Insérer une fiche ou une rubrique du bottin',
    placeholder: 'Indiquer id',
    icon: 'store',
    category: 'widgets',
    supports: {
        align: true,
        html: false,
    },
    example: {
        attributes: {
            id: '12345',
        },
    },
    edit: function ({className, setAttributes, attributes}) {

        const bottinCompleter = {
            name: 'acbottin',
            triggerPrefix: '::',
            options(search) {
                if (search) {
                    return apiFetch({
                        path: 'acmarche/bottin/' + search
                    });
                }
                return [];
            },
            isDebounced: true,
            getOptionLabel(fiche) {
                return <span>{fiche.slug} <small>{fiche.id}</small></span>;
            },
            // Declares that options should be matched by their name
            getOptionKeywords: fiche => [fiche.slug, fiche.id],
            // completions should be removed, but then spawn setPost
            getOptionCompletion(fiche) {
                return {
                    action: 'replace',
                    value: updateAttributesId(fiche.id),
                };
            },
        };

        // Our filter function
        function appendBottinCompleter(completers, blockName) {
            return blockName === 'acmarche-block/bottin' ?
                [...completers, bottinCompleter] :
                completers;
        }

        addFilter(
            'editor.Autocomplete.completers',
            'acbottin/autocompleters-bottin',
            appendBottinCompleter
        );

        const {ShowFull} = attributes;

        const updateAttributesId = (newContent) => {
            const blockSelected = wp.data.select('core/block-editor').getSelectedBlock();
            console.log(blockSelected);
            // blockSelected.attributes.id = newContent.toString(); //not refresh block
            setAttributes({id: newContent.toString()});//refresh block, bug with several times the same block
        };

        let blockContent = 'Indiquez le nom de la fiche';
        console.log('ici');
        if (parseInt(attributes.id) > 0) {
            blockContent = <ServerSideRender
                block="acmarche-block/bottin"
                attributes={attributes}
            />;
        }

        const FullFicheToggleControl = withState({
            isFullDisplay: ShowFull,
        })(({isFullDisplay, setState}) => (
            <ToggleControl
                label="Afficher la fiche complète"
                help={isFullDisplay ? 'Has fixed background.' : 'No fixed background.'}
                checked={isFullDisplay}
                onChange={value => {
                    console.log(value);
                    setAttributes({showFull: value});
                    setState({isFullDisplay: value});
                }}
            />
        ));

        return (<>
                <InspectorControls>
                    <PanelBody title={'Paramètres de la fiche'}>
                        <FullFicheToggleControl/>
                    </PanelBody>
                </InspectorControls>
                <RichText
                    tagName="p"
                    placeholder="Modifier"
                    withoutInteractiveFormatting
                    onChange={(value) => {
                    }}
                    aria-autocomplete="list"
                />
                <Disabled>
                    {blockContent}
                </Disabled>
            </>
        )
    },
});

Для автоматического завершения я должен был добавить API отдыха

myplugin. php

<?php

function register_block_bottin() {
    $asset_file = include( plugin_dir_path( __FILE__ ) . 'build/block.asset.php' );

    // Register block styles for both frontend + backend.
    wp_register_style(
        'bottin-block-style-css', // Handle.
        plugins_url( 'bottin/src/blocks.style.build.css', dirname( __FILE__ ) ), // Block style CSS.
        array( 'wp-editor' ), // Dependency to include the CSS after it.
        filemtime( plugin_dir_path( __DIR__ ) . 'bottin/src/blocks.style.build.css' ) // Version: File modification time.
    );

    // Register block editor script for backend.
    wp_register_script(
        'bottin-autocompleter',
        // Handle.
        plugins_url( 'bottin/build/block.js', dirname( __FILE__ ) ),
        // Block.build.js: We register the block here. Built with Webpack.
        $asset_file['dependencies'],
        $asset_file['version'],
        true // Enqueue the script in the footer.
    );

    wp_enqueue_style( 'bottin-block-style-css' );
    wp_enqueue_script( 'bottin-autocompleter' );

    register_block_type( 'acmarche-block/bottin',
                         [
                             'attributes'      => [
                                 'showFull' => [
                                     'type'    => 'boolean',
                                     'default' => false,
                                 ],
                                 'id'       => [
                                     'type' => 'string',
                                 ],
                             ],
                             'render_callback' => 'bottin_render_callback'
                         ]
    );
}

function bottin_render_callback( $attributes ) {
    $id       = (int) $attributes['id'];
    $showFull = (bool) $attributes['showFull'];
    if ( ! $id ) {
        return '';
    }

    $render        = new BottinRender();
    $block_content = $render->renderFiche( $id, $showFull );//return html

    return $block_content;
}

add_action( 'init', 'register_block_bottin' );
/**
 * This is our callback function that embeds our phrase in a WP_REST_Response
 *
 * @param WP_REST_Request $request
 *
 * @return mixed|WP_REST_Response
 */
function rest_response_bottin( $request ) {
    $search = null;
    if ( isset( $request['search'] ) ) {
        $search = $request['search'];
    }

    $elastic = new BottinElastic( 'marchebe' );
    $result  = $elastic->search( $search );
    $hits    = $result['hits'];
    $total   = $hits['total'];
    $data    = [];
    $i       = 0;
    foreach ( $hits['hits'] as $hit ) {
        $post               = $hit['_source'];
        $data[ $i ]['slug'] = $post['name'];
        //$data[ $i ]['localite'] = $post['localite'];
        $data[ $i ]['id'] = $post['id'];
        $i ++;
    }

    return rest_ensure_response( $data );
}

/**
 * This function is where we register our routes for our example endpoint.
 */
function register_rest_route_bottin() {
    // register_rest_route() handles more arguments but we are going to stick to the basics for now.
    register_rest_route( 'acmarche/',
                         '/bottin/(?P<search>.*+)',
                         array(
                             'methods'  => WP_REST_Server::READABLE,
                             'args'     => array(
                                 'search' => array(
                                     'validate_callback' => function ( $param, $request, $key ) {
                                         return is_string( $param );
                                     }
                                 ),
                             ),
                             // Here we register our callback. The callback is fired when this endpoint is matched by the WP_REST_Server class.
                             'callback' => 'rest_response_bottin',
                         ) );
}

add_action( 'rest_api_init', 'register_rest_route_bottin' );
?>

У меня все еще есть ошибка, если в моей статье только мой блок, refre sh хорошо работает с setAttributes, но если у меня есть мой блок несколько раз, я должен выбрать текущий блок и обновить его атрибут, кроме как через setAttributes, потому что он обновляет первый найденный блок, а не тот, который записывается

blockSelected.attributes.id = newContent.toString(); //not refresh block
setAttributes({id: newContent.toString()});//refresh block but not the current block
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...