Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[4.0.0] javascript error using AutoComplete component #10542

Closed
manooweb opened this issue Oct 12, 2018 · 26 comments
Closed

[4.0.0] javascript error using AutoComplete component #10542

manooweb opened this issue Oct 12, 2018 · 26 comments

Comments

@manooweb
Copy link
Contributor

@manooweb manooweb commented Oct 12, 2018

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]
@manooweb
Copy link
Contributor Author

@manooweb manooweb commented Oct 12, 2018

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.

Loading

@youknowriad
Copy link
Contributor

@youknowriad youknowriad commented Oct 12, 2018

Does this ring any bells for you @iseulde?

Loading

@ellatrix
Copy link
Member

@ellatrix ellatrix commented Oct 12, 2018

Looking

Loading

@ellatrix
Copy link
Member

@ellatrix ellatrix commented Oct 12, 2018

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?

Loading

@manooweb
Copy link
Contributor Author

@manooweb manooweb commented Oct 12, 2018

@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.

Loading

@manooweb
Copy link
Contributor Author

@manooweb manooweb commented Oct 17, 2018

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

Loading

@manooweb
Copy link
Contributor Author

@manooweb manooweb commented Oct 18, 2018

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.

Loading

@manooweb manooweb changed the title [4.0.0-rc.1] javascript error using AutoComplete component [4.0.0] javascript error using AutoComplete component Oct 19, 2018
@petenelson
Copy link

@petenelson petenelson commented Oct 24, 2018

Just updated to 4.1 and it's still occurring.

Loading

@manooweb
Copy link
Contributor Author

@manooweb manooweb commented Oct 24, 2018

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.

Loading

@leogermani
Copy link

@leogermani leogermani commented Nov 6, 2018

Hi @iseulde ,

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

Thanks!

Loading

@petenelson
Copy link

@petenelson petenelson commented Nov 14, 2018

Still an issue as of 4.3

Loading

@thatdevgirl
Copy link

@thatdevgirl thatdevgirl commented Nov 28, 2018

I am also seeing this issue in 4.5.1.

Loading

@thatdevgirl
Copy link

@thatdevgirl thatdevgirl commented Nov 29, 2018

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

Loading

@igorbenic
Copy link

@igorbenic igorbenic commented Dec 5, 2018

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.

Loading

@galikpali
Copy link

@galikpali galikpali commented Dec 12, 2018

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} />

Loading

@abhijitrakas
Copy link
Contributor

@abhijitrakas abhijitrakas commented Feb 25, 2019

@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.

Loading

@manooweb
Copy link
Contributor Author

@manooweb manooweb commented Feb 26, 2019

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

Loading

@JordanPak
Copy link

@JordanPak JordanPak commented Jan 21, 2020

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;
};

Loading

@jfsenechal
Copy link

@jfsenechal jfsenechal commented Mar 2, 2020

@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

Loading

@JordanPak
Copy link

@JordanPak JordanPak commented Mar 3, 2020

@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 :(

Loading

@vavra7
Copy link

@vavra7 vavra7 commented Apr 20, 2020

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

Loading

@ellatrix
Copy link
Member

@ellatrix ellatrix commented Apr 23, 2020

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.

Loading

@paaljoachim
Copy link
Contributor

@paaljoachim paaljoachim commented Feb 20, 2021

Hi @sirreal Jon

Can the fix in Calypso here: Automattic/wp-calypso#47907
Be transferred over here?
Thanks.

Loading

@sirreal
Copy link
Member

@sirreal sirreal commented Feb 22, 2021

@paaljoachim The fix you referenced removes the problematic component, that isn't really applicable here.

A way forward following @ellatrix's thinking (#10542 (comment)) would be:

  • Rename Autocomplete to __unstableAutocomplete.
  • Make Autocomplete a wrapper for __unstableAutocomplete with a deprecation notice.
  • Export both the names Autocomplete and __unstableAutocomplete.

This should maintain backwards compatibility and make it clear that the component is not intended for external usage according to documentation on Experimental and Unstable APIs.

Loading

@paaljoachim
Copy link
Contributor

@paaljoachim paaljoachim commented Feb 22, 2021

Thanks Jon @sirreal

I'll ping Greg @gziolo and Miguel @mcsf and see if they have the opportunity to take a closer look.

Loading

@mcsf
Copy link
Contributor

@mcsf mcsf commented Feb 22, 2021

I'll ping Greg and Miguel @mcsf and see if they have the opportunity to take a closer look.

No need for a closer look, as nothing has really changed since Ella's comments from last year, and Jon summed up well going about deprecating the Autocomplete component. Meanwhile, the need for autocomplete to be a hook is something that Ella and I happened to discuss last week, so it's a known need. That would open up possibilities in terms of untangling other components — IIRC, most of RichText could become hook-based in the future.

This issue, as it stands, is no longer very useful, so I recommend closing it. Two possible actions that remain are the deprecation and the implementation of an autocomplete hook. If someone out there can own them, great; otherwise, they'll have to wait.

Loading

@mcsf mcsf closed this Feb 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet