Gutenberg: [4.0.0] javascript error using AutoComplete component

Created on 12 Oct 2018  路  22Comments  路  Source: WordPress/gutenberg

Describe the bug
The AutoComplete component example documented here https://github.com/WordPress/gutenberg/tree/master/packages/components/src/autocomplete

works fine with Gutenberg 3.9.0 but with Gutenberg 4.0.0-rc.1 a javascript errors occurs and no component is displayed.

To Reproduce
Steps to reproduce the behavior:

  1. Code a component exactly like the documented example
  2. Run it in the Gutenberg context
  3. See Gutenberg Error on screen
  4. See javascript Error in the console of the developer tools bar

Expected behavior
A simple AutoComplete component has to work fine with Gutenberg 4.0.0-rc.1

Screenshots
image

Desktop (please complete the following information):

  • OS: windows 10
  • Browser chrome 69
  • Version [e.g. 22]
[Feature] Rich Text [Type] Bug

Most helpful comment

Hopefully this is helpful. I really needed an Autocomplete component for the project I am working on right now, so I created a super simple one. https://gist.github.com/thatdevgirl/e20f72d5b985c6eab441bdf491b3edf0

All 22 comments

AutoComplete componentDidUpdate() seems to be rewritten and need a record property to pass it to the isCollapsed function of the RichText Component.
In a case where we don't use the AutoComplete component with RichText the property record is undefined and isCollapsed() function causes the error.

Does this ring any bells for you @iseulde?

Looking

Unsure how we can make it work again with a plain contenteditable field without introducing a lot of code. @manooweb How are you using the AutoComplete component? In combination with RichText or something else? How are you using it inside a block?

@iseulde no I am inside a plugin sidebar and I just put the code exactly like it is documented in the readme file I linked above.

Screenshot with Gutenberg 3.9.0

image

Autocomplete component is wrapped in a span tag in our jsx render code of our parent component. This is not a pure function component but a class component with state. I initialize completers inside the constructor and pass this property to Autocomplete with this.completers.
This just the little things that are different with the code example in the documentation.

This is really the component which is inside @wordpress/components and not the other one which is inside the editor package and which is a wrapper.

So, I continue to develop my component with the Autocomplete of Gutenberg 3.9.0 with a simple contentEditable and it works fine. I coded a promise with apiFetch() call to get posts filtered by language to initialize the options of the Autocomplete component.
When I switch to Gutenberg 4.0.0-rc.1, it is broken for the same reason that I opened the issue.

Then, I'm trying to integrate Autocomplete 3.9.0 in our code but now I have a lodash error which seems to be triggered by the "compose" fonction of Autocomplete component

image

Any kind of help or guidance will be appreciate to continue in the right direction to finish this feature.

Thank you so much

Well, it's ok for me now. I solved my last problem. I just did a mistake with import syntax that I have to change for putting the component outside Gutenberg.
So I integrated directly in our code the Autocomplete component from Gutenberg 3.9.0
The first issue is always there if you want to use the component as it is explained in its documentation.

I'd prefer that the the Autocomplete component stay in Gutenberg to maintain it and continue to work fine with contentEditable as in Gutenberg 3.9.0.

Just updated to 4.1 and it's still occurring.

Thanks @petenelson :-)
I dived deeper in code and understood I have to use RichText component which is using Autocomplete component but I did not find yet how to do it properly.

Hi @iseulde ,

Any chances this component is fixed to the release? Is this been worked on?

Thanks!

Still an issue as of 4.3

I am also seeing this issue in 4.5.1.

Hopefully this is helpful. I really needed an Autocomplete component for the project I am working on right now, so I created a super simple one. https://gist.github.com/thatdevgirl/e20f72d5b985c6eab441bdf491b3edf0

If you add record={{}} to the Autocomplete component it should work but I am not sure how and when should this record be updated. It receives start, end, format and text values but I have yet to find how they're managed.

I've managed to figure it out.

Try to import RichText from wp.editor and use it instead of autocomplete.

<RichText value={this.state.value} onChange={this.setValue} autocompleters={completer} />

@thatdevgirl Thanks for the snippet. It saves lives. Just one question could we use dynamic ID for autocomplete uisng withInstanceId? Something like I have added here.

I definitively doesn't use this component which is too complex for our need.
I inspired myself from another one more simple component : urlInputButton in editor components
https://github.com/WordPress/gutenberg/blob/master/packages/editor/src/components/url-input/index.js

I simplified it and integrated it in our own code to be sure we will be able to maintain it as we want even if it would be preferable to have one in Gutenberg code
https://github.com/polylang/polylang-gutenberg/blob/master/js/sidebar/components/translation-input/index.js

I think I found a way around this. We already know that this _Autocomplete_ component works for the block and user completion, but it's working within the RichText control, so I simply filtered the autocompleters to use a custom one instead of the two default ones:

wp.hooks.addFilter(
    'editor.Autocomplete.completers',
    'jp/addCompleters',
    addCompleters,
);

This handles overriding the default autocompleters:

/**
 * Add our custom WPCompleters to list of autocompleters (callback)
 *
 * @param  {array}  completers existing autocomplete completers
 * @param  {string} blockName  block type the filter is running on
 * @return {array}  completers just our new companyCompleter if the right block(s)
 * @since  1.0.0
 */
const addCompleters = ( completers, blockName ) => {
    switch ( blockName ) {
        case 'jp/company' :
            completers = [ getCompleter( 'jp_company' ) ];
            break;

        case 'jp/statistic' :
            completers = [ getCompleter( 'jp_statistic' ) ];
            break;

        default:
            break;
    }

    return completers;
};

Here's the helper that returns an instance (object) of autocompleter instructions. This one fetches posts of the post type from a site network via custom REST endpoint:

/**
 * Configuration for company <Autocomplete>
 *
 * @type   {WPCompleter}
 * @param  {string}       postType  CPT key
 * @return {object}                 Autocomplete completer properites
 * @since  1.0.0
 */
const getCompleter = postType => {
    return {
        name: 'jp/' + postType,

        // prefix that triggers this completer
        triggerPrefix: '',

        // option data
        options( search ) {
            const args = {
                post_type: postType,
            };

            if ( search ) {
                args.search = encodeURIComponent( search );
            }

            return wp.apiFetch( { path: addQueryArgs( '/jp/v1/network-posts', args ) } );
        },

        // since we're doing API fetch
        isDebounced: true,

        // returns option label
        getOptionLabel( post ) {
            return <span>{ post.post_title } <small>({ sites[ post.BLOG_ID - 1 ].label })</small></span>;
        },

        // options should be matched by their name
        getOptionKeywords: post => [ post.post_title, post.post_content ],

        // completions should be removed, but then spawn setPost
        getOptionCompletion( post ) {
            return {
                action: 'replace',
                value: setPost( parseInt( post.BLOG_ID ), post.ID, post.post_title ),
            };
        },
    };
};

This example assumes some things that might not work for some situations:

  1. The block you're editing doesn't seem to be accessible from this context. You can set the attributes manually, but that doesn't trigger the state change.
  2. This will alter all <RichText> controls in the block(s) being filtered, so that may need to be adjusted if you have multiple text controls and only want the autocomplete in one of them.

^ thing 1 explained:

/**
 * Set network post ID/title for selected block
 *
 * @param {integer} blogID    network blog ID
 * @param {integer} postID    company post ID
 * @param {string}  postTitle company post title
 * @since 1.0.0
 */
const setPost = ( blogID, postID, postTitle ) => {
    const block = wp.data.select( 'core/block-editor' ).getSelectedBlock();

    // block.setAttributes() isn't available here! 馃槷
    block.attributes.postBlogID = blogID;
    block.attributes.postID = postID;
    block.attributes.postTitle = postTitle;
};

@JordanPak I got around the problem like you

I still have a bug, by updating the attribute as you do : block.attributes.postBlogID = blogID;
The block is not refreshed
if I update with setAttributes the block refreshes well but if I have my block several times in an article setAttributes does not update the block being edited but the first one it finds

Can you help me ?

Here is my code

https://stackoverflow.com/questions/60366649/wordpress-gutenberg-autocompleters-no-auto-completion-completes/60495563#60495563

@JordanPak I got around the problem like you

I still have a bug, by updating the attribute as you do : block.attributes.postBlogID = blogID;
The block is not refreshed
if I update with setAttributes the block refreshes well but if I have my block several times in an article setAttributes does not update the block being edited but the first one it finds

Can you help me ?

Here is my code

https://stackoverflow.com/questions/60366649/wordpress-gutenberg-autocompleters-no-auto-completion-completes/60495563#60495563

@jfsenechal I am not having an issue where editing one block affects the properties or state of another block, but since I haven't figured out how to use block.setAttributes() in that setPost() function, the "state" of the block with the autocomplete doesn't fire off consistently :(

Still does not work.

Using example of autocomplete from:
https://developer.wordpress.org/block-editor/components/autocomplete/
throws exception:
TypeError: Cannot read property 'start' of undefined

Unfortunately, this component wasn't really meant to be exported for use in plugins and I highly discourage using this component and see it as experimental. I guess we'll (have to) keep it around in its current form, but at some point I don't expect it to be used by Gutenberg core anymore.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

davidsword picture davidsword  路  3Comments

franz-josef-kaiser picture franz-josef-kaiser  路  3Comments

pfefferle picture pfefferle  路  3Comments

aaronjorbin picture aaronjorbin  路  3Comments

moorscode picture moorscode  路  3Comments