svelte icon indicating copy to clipboard operation
svelte copied to clipboard

value change should not trigger when typeing ( compositionstart -> compositionend )

Open i18nsite opened this issue 1 year ago • 11 comments

Describe the problem

https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionstart_event When using the input method, the user has not formally entered text and the value change event should not be triggered. CleanShot 2024-09-11 at 10 41 45

You can refer to the implementation in vue

https://github.com/vuejs/core/blob/main/packages/runtime-dom/src/directives/vModel.ts CleanShot 2024-09-11 at 10 44 36

now svelte is CleanShot 2024-09-11 at 10 58 50

Describe the proposed solution

When the user starts inputting Chinese characters using the Pinyin input method, the compositionstart event will be triggered. When the composition of a text paragraph is completed or canceled, the compositionend event will be fired.

That is to say, when we start inputting Chinese, a compositionstart event will be triggered. During the Chinese input process, the compositionstart event will not be triggered again. Finally, the compositionend event will be triggered when the Chinese input is completed.

And after experiments, it was found that when inputting Chinese, compositionstart is triggered before the input event.

Importance

nice to have

i18nsite avatar Sep 11 '24 02:09 i18nsite

What exactly are you referring to? My assumption would be that you want to have the behavior of bind:value changed for input and textarea?

brunnerh avatar Sep 11 '24 07:09 brunnerh

I'm assuming this is for contenteditable rather than input and textarea as they should just work.

Having worked on Lexical, I can tell you that it's really difficult to get IME input correct. Listening to compositionstart and compositionend is simply not good enough. This doesn't take into account that content can be inserted via other methods during this time – such as copy+paste, screenreaders, or speech to text etc and thus you can't always reliably state the value. You also will need a DOM Mutation Observer to capture changes that sometimes happen but don't invoke events – such as when you're on some browsers in Android.

If you want to reliably capture text input yourself, it's recommended that you use a rich text library such as ProseMirror or Lexical instead of trying to do it yourself.

trueadm avatar Sep 11 '24 08:09 trueadm

the user has not formally entered text

If you imply that the semi-composed text is meaningless, then the same can be said about the unfinished word or sentence/query. A composition-aware debouncer makes more sense to me here.

the value change event

A reminder: for the text fields, the change event is fired when the field loses focus (the user has finished editing the text), while the input event, which is used in bind:value, is fired immediately after any change. And Svelte has no analogue to Vue's v-model.lazy, which uses a change event.

I'm assuming this is for contenteditable rather than input and textarea as they should just work.

vModelText typing supposes it is used on input and textarea. And contenteditable brings more problems than solves, but it's another topic.

7nik avatar Sep 11 '24 09:09 7nik

What exactly are you referring to? My assumption would be that you want to have the behavior of bind:value changed for input and textarea?

I'm writing a real-time search that will trigger the search when the user enters new content. If the user does not enter the complete content using the Chinese input method, then the value binding should not trigger the search. If using vue, the performance is as expected, but using svelte is not.

i18nsite avatar Sep 11 '24 23:09 i18nsite

What exactly are you referring to? My assumption would be that you want to have the behavior of bind:value changed for input and textarea?

I'm writing a real-time search that will trigger the search when the user enters new content. If the user does not enter the complete content using the Chinese input method, then the value binding should not trigger the search. If using vue, the performance is as expected, but using svelte is not.

What element is the search?

trueadm avatar Sep 11 '24 23:09 trueadm

What exactly are you referring to? My assumption would be that you want to have the behavior of bind:value changed for input and textarea?

I'm writing a real-time search that will trigger the search when the user enters new content. If the user does not enter the complete content using the Chinese input method, then the value binding should not trigger the search. If using vue, the performance is as expected, but using svelte is not.

What element is the search?

input

i18nsite avatar Sep 11 '24 23:09 i18nsite

I'm assuming this is for contenteditable rather than input and textarea as they should just work.

Having worked on Lexical, I can tell you that it's really difficult to get IME input correct. Listening to compositionstart and compositionend is simply not good enough. This doesn't take into account that content can be inserted via other methods during this time – such as copy+paste, screenreaders, or speech to text etc and thus you can't always reliably state the value. You also will need a DOM Mutation Observer to capture changes that sometimes happen but don't invoke events – such as when you're on some browsers in Android.

If you want to reliably capture text input yourself, it's recommended that you use a rich text library such as ProseMirror or Lexical instead of trying to do it yourself.

CleanShot 2024-09-12 at 07 36 37

I tested it on my Mac. When inputting Chinese, using shortcut keys to paste does not work. Pasting with the mouse will cause the focus to be lost and trigger a change event.

For me, triggering a value modification check on both compositionend and input works as expected.

i18nsite avatar Sep 11 '24 23:09 i18nsite

I'm assuming this is for contenteditable rather than input and textarea as they should just work. Having worked on Lexical, I can tell you that it's really difficult to get IME input correct. Listening to compositionstart and compositionend is simply not good enough. This doesn't take into account that content can be inserted via other methods during this time – such as copy+paste, screenreaders, or speech to text etc and thus you can't always reliably state the value. You also will need a DOM Mutation Observer to capture changes that sometimes happen but don't invoke events – such as when you're on some browsers in Android. If you want to reliably capture text input yourself, it's recommended that you use a rich text library such as ProseMirror or Lexical instead of trying to do it yourself.

CleanShot 2024-09-12 at 07 36 37

I tested it on my Mac. When inputting Chinese, using shortcut keys to paste does not work. Pasting with the mouse will cause the focus to be lost and trigger a change event.

For me, triggering a value modification check on both compositionend and input works as expected.

CleanShot 2024-09-12 at 07 54 03 or use KeyboardEvent.isComposing https://developer.mozilla.org/zh-CN/docs/Web/API/KeyboardEvent/isComposing

i18nsite avatar Sep 11 '24 23:09 i18nsite

When inputting Chinese, using shortcut keys to paste does not work

Different IMEs can have vaguely different behaviour. Mine does allow pasting while in composing. I remember debugging a VSCode problem with the composing. In that Github issue, the people using Simplified Chinese IME reported very different behaviour than mine.

Also, not everyone wants this "value change not triggering during composition". Changing this behaviour is a weird breaking change in my opinion. I think you can manually handle it on your own with on:input (or oninput in svelte 5) instead.

jasonlyu123 avatar Sep 12 '24 02:09 jasonlyu123

When inputting Chinese, using shortcut keys to paste does not work

Different IMEs can have vaguely different behaviour. Mine does allow pasting while in composing. I remember debugging a VSCode problem with the composing. In that Github issue, the people using Simplified Chinese IME reported very different behaviour than mine.

Also, not everyone wants this "value change not triggering during composition". Changing this behaviour is a weird breaking change in my opinion. I think you can manually handle it on your own with on:input (or oninput in svelte 5) instead.

Does svelte have something similar to vue's Modifiers?

https://v2.vuejs.org/v2/guide/forms.html#Modifiers

If there is such a thing, it can be more convenient to customize the behavior of bind:value

or else , define new bind, for example: bind:valime

i18nsite avatar Sep 12 '24 02:09 i18nsite

Svelte doesn't have modifiers. The simplest way is

<input bind:value on:compositionstart={() => composing = true} on:compositionend={() => composing = false} />

and do nothing when composing is true.

7nik avatar Sep 12 '24 15:09 7nik