-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Fix adding links from the autocompleter #10500
Conversation
resetState( event ) { | ||
// URLInput's autocomplete list can trigger onClickOutside on the link container's popover. | ||
// Return early here if the click originated from one of the autocomplete suggestions. | ||
if ( hasIn( event, [ 'target', 'classList' ] ) && includes( event.target.classList, 'editor-url-input__suggestion' ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be nice to be able to avoid checking the class here, but I'm short of other ideas beyond having LinkContainer manage a ref to the URLInput's popover.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this is a bit unfortunate.
|
Hi @iseulde - the change was added in the RichText refactor: Before that, there wasn't an I'll have a look at adding a case to the e2e links test. |
61cd065
to
537b18d
Compare
Why are the link suggestions not in the same popover? That's a bit strange. |
@iseulde - Not sure, the input is a separate component, and I imagine it's based on other autocomplete implementations. I'll try to think of some other ways to fix this today. |
…riginate from the autocomplete popover
…n they originate from the autocomplete popover" This reverts commit 17d4cf8.
537b18d
to
cd0c1e0
Compare
Hey @iseulde I've changed the implementation to use a ref now instead of checking class names. I did take a look at if it would be possible to un-nest the suggestions from their popover, but it was a bit too involved. |
// so onClickOutside fails to detect that a click on a suggestion occured in the | ||
// LinkContainer. Detect clicks on autocomplete suggestions using a ref here, and | ||
// return early if so. | ||
if ( hasIn( this, [ 'autocompleteRef', 'contains' ] ) && this.autocompleteRef.contains( event.target ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the check?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the user attempted to click outside of the popover when the autocomplete list hadn't been displayed, this.autocompleteRef
would be unset. Checking for contains
seems to be the safest option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using hasIn
like this makes me think that this condition is a browser compatibility check for Node.contains()
. This isn't necessary since Node.contains()
works in all modern browsers.
I think a clearer way to convey what's happening is to simply check for the presence of the ref.
if ( hasIn( this, [ 'autocompleteRef', 'contains' ] ) && this.autocompleteRef.contains( event.target ) ) { | |
if ( this.autocompleteRef && this.autocompleteRef.contains( event.target ) ) { |
Using ref.contains sounds better! |
// so onClickOutside fails to detect that a click on a suggestion occured in the | ||
// LinkContainer. Detect clicks on autocomplete suggestions using a ref here, and | ||
// return early if so. | ||
if ( hasIn( this, [ 'autocompleteRef', 'contains' ] ) && this.autocompleteRef.contains( event.target ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using hasIn
like this makes me think that this condition is a browser compatibility check for Node.contains()
. This isn't necessary since Node.contains()
works in all modern browsers.
I think a clearer way to convey what's happening is to simply check for the presence of the ref.
if ( hasIn( this, [ 'autocompleteRef', 'contains' ] ) && this.autocompleteRef.contains( event.target ) ) { | |
if ( this.autocompleteRef && this.autocompleteRef.contains( event.target ) ) { |
@@ -96,6 +105,9 @@ class LinkContainer extends Component { | |||
this.onChangeInputValue = this.onChangeInputValue.bind( this ); | |||
this.setLinkTarget = this.setLinkTarget.bind( this ); | |||
this.resetState = this.resetState.bind( this ); | |||
this.bindAutocompleteRef = this.bindAutocompleteRef.bind( this ); | |||
|
|||
this.autocompleteRef = createRef(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's confusing, I think, to see a mix of createRef()
refs and callback refs.
This line here is redundant since bindAutocompleteRef
will overwrite this.autocompleteRef
when the component is mounted.
The quick way to address this is to delete this line.
this.autocompleteRef = createRef(); |
A nicer approach, I think, would be to update URLInput
to use createRef()
refs. Then, LinkEditor
can simply override the ref by passing a prop.
class URLInput extends Component {
constructor( { autocompleteRef } ) {
super( ...arguments );
this.autocompleteRef = autocompleteRef || createRef();
}
render() {
...
return (
...
<div
className="editor-url-input__suggestions"
...
ref={ this.autocompleteRef }
>
...
);
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it! Thanks for adding tests.
Awesome, thanks @talldan for the heads up and doing the fix. Let's see how the release process goes :) |
* Use a ref to detect clicks in the autocomplete suggestion list * Add e2e tests to test for regression of link autocomplete issue
Fixes #10496
Description
When adding links from the autocompletion list, the
onClickOutside
handler on the LinkContainer popover was being triggered, causing the link not to be set and triggering closure of the popover.This fix adds a clause at the start of the
onClickOutside
handler, detecting if the click originated from a autocomplete entry and returning early if so.How has this been tested?
Types of changes
Bug fix (non-breaking change which fixes an issue)
Checklist: