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

a beforeInsertText function to accept/reject text insertion #5050

Open
miquik opened this issue Jul 15, 2022 · 7 comments
Open

a beforeInsertText function to accept/reject text insertion #5050

miquik opened this issue Jul 15, 2022 · 7 comments
Labels

Comments

@miquik
Copy link

miquik commented Jul 15, 2022

Problem
I'm working on custom plugin which prevent text insertion under some conditions. I successfully do it by overriding insertText function and it works on slate "side" but, considering that text insertion "follow" beforeinput event, the text is in any case inserted in DOM even if insertText inserts nothing

Solution
Considering that in beforeinput event some inputType are cancellable (i.e. for example insertText), it would be useful to have a beforeInsertText function to cancel the beforeinput event (it should be called somewhere within the onDOMBeforeInput function)

@miquik miquik added the feature label Jul 15, 2022
@dylans
Copy link
Collaborator

dylans commented Jul 15, 2022

We're happy to review and consider a PR for this. It should be pretty straightforward to add. Ping us on the Slack group if you need guidance.

@BitPhinix
Copy link
Contributor

BitPhinix commented Jul 18, 2022

Hmm, I feel like this could be solved somehow with the current api as well 🤔 Not sure about the details yet, but especially on android, we can't assume that beforeInput events are cancelable. What we can do however is to undo the DOM changes if the state after the insertText doesn't match the DOM state. We have some places in the codebases that implicitly rely on the native insertText behavior, or at least that it causes a change. The 'native' handling is especially guilty of this, which is probably what causes issues with preventing inserts using it. But again - I haven't dug into this yet, so I might be missing something.

Also unrelated to that - limiting text input using insertText for composed text won't work with the current implementation regardless

@miquik
Copy link
Author

miquik commented Jul 18, 2022

Hmm, I feel like this could be solved somehow with the current api as well

Well what I could do is to prevent insertion on keydown event, but I should consider all keys and modifier and I think it would be painful

What we can do however is to undo the DOM changes if the state after the insertText doesn't match the DOM state.

Isn't try to "undo the DOM" too complicated? Could you please give some hint how to proceed this way?

@BitPhinix
Copy link
Contributor

I'm sorry, I haven't explained it well enough 😅

We, by default, preventDefault all beforeInput events, except for 'native' events and composition. So by default (except in these 2 cases), overwriting the editor.insertText behaviour to prevent text from being inserted would work just fine since the browser never modifies the DOM in the first place. (you can try this out by commenting out the line here)

But, because we have the 'native' event handling, we add an implicit requirement to the behavior of the editor.insertText function to cause an update inside the changed node. The 'native' event handling let's the beforeInput event go through and defers the changes until after the browser has committed the changes to the DOM. It then calls the deferred editor.insertText to commit the changes to the slate state. Once the changes are commited to the slate state, slate/react will reconconciliate the DOM to match the current state (mainly here for simple changes). But if you don't change the slate state inside the deferred operations, slate/react will never cause that react element to update and thus your dom and slate state are out of sync. So the real solution to this is to cause the element to re-render regardless of if you changed the corresponding slate node in the deferred changes or not.

I hope that explains it well enough. If you want I can put a pr in for this - but it might take 1-2 weeks until I find the time to do so

@miquik
Copy link
Author

miquik commented Jul 18, 2022

Thank you very much, now I have some little more clear view of what happen under the hood. Basically, I have to find a way to re-render element even if insertText changes nothing. It would be great if I can "control" this behaviour directly from insertText

@miquik miquik closed this as completed Jul 19, 2022
@miquik
Copy link
Author

miquik commented Aug 23, 2022

I'm here again with same problem.
I was able to force element to re-render but now I have this behaviour:

problem

@miquik miquik reopened this Aug 23, 2022
@delijah
Copy link
Contributor

delijah commented Oct 16, 2023

Same here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants