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 onInput events inside decorator nodes #2823
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
if (!event.target.closest('[data-lexical-decorator=true]')) { | ||
// We don't want the onInput to bubble, in the case of nested editors. | ||
event.stopPropagation(); | ||
} |
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.
I do not know what was the driver for adding this originally, but if nested editors can be only inside decorator nodes, then the proposed change is going to cross out this functionality entirely.
Does it need an additional check if the target node is inside a lexical editor instance?
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 ( | ||
target && | ||
target instanceof HTMLElement && | ||
!target.closest('[data-lexical-decorator=true]') |
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.
On https://developer.mozilla.org/en-US/docs/Web/API/Element/closest The closest() method of the Element interface traverses the element and its parents (heading toward the document root) until it finds a node that matches the specified CSS selector.
Is there a risk to impact the performance, as on each event, there could be a full tree traversal to the top?
Thank you! Would you mind adding a bit more context on your use case and how the current AFAIK this should prevent bubbling but you can still handle whatever you need within your own component. If you need to pass any data outside the editor you can leverage a React Context to send and receive information (inc. your own custom event subscriptions) or commands to certain extend |
My component is listening for user input changes and depending on the value converts it to a different thing. All this happens internally inside the component (It doesn't send anything outside the editor). Because lexical stops input event propagation my component does not receive the event. |
@zurfyx see Discord thread: https://discord.com/channels/953974421008293909/1006976156748222464/1007575453076299797 |
@zurfyx does this PR need anything else to be able to move this forward? |
Thinking about @echarles concern, it does seem less-than-ideal to run this check on every single input event. I'm wondering if we can just get rid of this stopPropagation call. I'm looking into whether it makes sense to have nested editors outside of DecoratorNodes. I think that it's possible - for instance, we've discussed using nested editors for table cells. Give me and @zurfyx a bit more time on this, if you don't mind. Sorry for the delay. |
I've tried to test this with PollNode which also has |
I have a custom component with a Regarding the performance concern: I do not think this would cause any big issues as the frequency of the events is not that tense, however, I do agree that this is "less-than-ideal" and avoiding having the condition (and removing stop propagation) would be preferable but because I am not familiar with the code and do not know the consequences, I cannot insist on this change. (Though I was trying to dig up why it was added originally, and found that it was added here and perhaps @trueadm who added it originally has more insights) |
p.s. @acywatson I guess it was not intentionally commented out and merged into the |
I'm still struggling to reproduce the issue, e.g. I've added content editable into <div contentEditable={true} onInput={console.log} style={{border: '1px solid red'}}>
This is contenteditable
</div> And it gets input events just fine. Is it different from what you have? Screen.Recording.2022-08-18.at.10.35.01.AM.mov |
Whoops - I was testing locally on my typedoc branch lol |
It works for me the way you add it. My case though much more complicated. I am trying to wrap a legacy component into the decorator node, where the component is something weirdly nested as Also, I am on React v16.14.0, and I know React 17 handles events differently, so it can be another reason why it is not reproducible on the playground. If this is caused by Backbone.js, then I guess this is not a common use case and might not be worse to make a fix for it. I am going to investigate it on my side and perhaps it is going to be I'll update here once I have more information. Thank you. |
I upgraded my codebase to use React v17.0.2 and now this is no longer an issue. So apparently this was caused by React. I am going to close this PR unless you think this still needs to be fixed for those who have earlier React versions. Thanks for reviewing the PR and helping with it. |
Great to read that.
Does that change need to be reverted? |
We don’t actually support earlier versions of React than 17. We should document this somewhere and revert the change |
Change was reverted several days ago: #2849 PR welcome to update the docs re: React support version. Thanks all! |
Problem
Input elements inside decorator nodes do not receive
input
events because lexical stops propagation in the parent editor.Solution
Check if the target element of the input event is from a decorator node, if so - do not stop propagation of the event.
Related conversation in discord: https://discord.com/channels/953974421008293909/1006976156748222464/1007339073683337327