While an input method editor composes a character, why must a binding keep the in-progress text out of the model?
answer
- several keystrokes, one final character
- the control shows it, the model must not
- write-back is the destructive half
- suspend between start and end signals
- clear the flag on focus loss too
basics
~20 sIn-progress composition text is not a final character: it must appear in the control so the user can see and choose, but publishing it to the model feeds nonsense downstream, and writing it back can cancel the composition.
solid answer
~50 sComposing with an input method editor turns several keystrokes into one or more final characters, and the control must display the unfinished intermediate text so the user can see and select. The host reports those intermediate states as edits, so a per-keystroke binding will publish them. Two things then go wrong. Everything downstream of the model sees text the user never committed — counters count intermediate units, a live filter issues a request per state, a formatter rewrites the buffer. Worse, the downward half writes the model's value back into the control mid-composition, replacing the control's own composition buffer, which can cancel the composition, duplicate or drop characters and move the caret. So suspend both directions between the composition start and end signals, take the value once when composition ends, and clear the suspension on focus loss too. A commit-source binding needs none of this.
go deeper
Know that some input methods build one character from several keystrokes, so a field can hold text that is not final yet and a binding should not treat it as a value.
Explain the two directions: intermediates belong in the control and not in the model, and the model's write-back must be held while the control is composing.
Show the handling in order — suspend on start, hold both directions, take the value once at the end, clear on focus loss — and name the symptoms you would recognise in a bug report.
Treat multilingual input as an acceptance criterion for shared field components, and note that a commit-source default removes the class rather than mitigating it.
## What composition is Some text cannot be typed one character per key. An **input method editor** assembles a sequence of keystrokes into final characters: phonetic input resolved into ideographs, a dead key plus a vowel into an accented letter, a phone's predictive text replacing a whole word. While that assembly is in progress, the control must show the **unfinished text** — the user is choosing among candidates and needs to see what they are choosing. The platform brackets this window with composition start and end signals and reports the intermediate states as edits. The mechanics of those host events belong to the platform layer; what belongs to a binding is the decision of **what to do during the window**. ## Why the model must not see the window The intermediate text is a **user-interface artefact**, not a value. Everything that derives from the model treats it as a value anyway: - **Rules judging the value** run against text the user never committed, so a message flashes and clears while the user is mid-word. - **Counters and limits** measure intermediate units rather than final characters, so a remaining-characters count jumps around and a length cap can block a legal entry. - **Derived requests** fire once per intermediate state — a live filter or a lookup burning several calls for one word. - **Formatters** rewrite the buffer according to a value that does not exist yet. - A **submit** during the window would carry unfinished text. ## Why write-back is the dangerous half Reading intermediates is untidy; writing during composition is destructive. The control owns a composition buffer with its own caret and candidate state. When the framework asserts the bound value into the control mid-composition it **replaces that buffer**, and the observable results are: - the composition is cancelled and the candidate list disappears; - characters are duplicated, because the committed text is appended to text the control still held; - characters are dropped, because the write landed before the commit; - the caret jumps to the end, so the next keystroke continues in the wrong place. The rule follows directly: **do not write into a control while it is composing.** ## The handling shape 1. On the composition start signal, set a per-field *composing* flag. 2. While the flag is set, keep subscribing if you like, but **do not write the model** and above all **do not write the control**. The control renders its own buffer perfectly well without help. 3. On the composition end signal, read the control's value **once** and write it to the model as a single edit. 4. Clear the flag and allow downward writes again. 5. Clear the flag on **focus loss** too, so a field that loses focus mid-composition cannot get stuck with writes suspended. Step 5 is the one people leave out. Do not assume an end signal always arrives before a blur in every host and input method; the flag has to be recoverable. ## Adjacent cases with the same shape - **Predictive text and autocorrect** on touch keyboards replace a range of already-visible text rather than appending, and often arrive in the same bracketed window. A binding that assumed append-only edits mis-handles both. - **Dictation** streams partial transcriptions that are revised as more audio arrives — the same *not final yet* property. - **Commit-source bindings get this for free.** If the binding writes only on the committed-change event, its write already lands after composition finished, which is one honest reason to prefer a commit source for free-text fields in a multilingual product. | Binding source | Sees intermediate text? | Write-back risk during composition | |---|---|---| | per-edit, no composition handling | yes, every intermediate | high — can cancel or duplicate | | per-edit, suspended while composing | no | none, writes are held | | committed change | no | none, commit lands after the window | ## Reactivity models differ in how loudly this fails A runtime that re-asserts the bound value downward on every state write is the most exposed: publishing an intermediate immediately writes it back, so the damage is visible on the first composed word. A runtime with fine-grained tracking writes down only when the value actually differs from what it last wrote, so many compositions survive and the bug surfaces only when a formatter or a rule changes the value mid-window. A compile-time runtime generates the same subscription; nothing about compilation handles composition for you. Some frameworks' own bindings suspend during composition by default and hand-written listeners never do — which is exactly why replacing a binding with a listener is a behaviour change, not a refactor. ## How to answer this in an interview Say what composition is in one sentence, then split the answer: intermediates must reach the **control** and must not reach the **model**, and the write-back is the half that actually breaks input. Name the suspend-until-end handling and the focus-loss escape, and note that a commit-source binding sidesteps the whole thing.
- Which half of the binding actually breaks the composition, reading or writing?Writing. Reading intermediates only pollutes downstream work, which is recoverable. Asserting the bound value into the control mid-composition replaces the control's own composition buffer, which cancels the candidate list or duplicates and drops characters. Suspending the downward write is the fix that matters most.
- Why does a binding that commits on the change event need no composition handling?Because its only write happens when the edit is final, which is after the composition window has closed. It never observes intermediates and never writes during the window. That is a genuine argument for a commit source on free-text fields in a product with multilingual input.
- What breaks if the composing flag is cleared only on the composition end signal?A field that loses focus mid-composition can be left with writes suspended, so it stops accepting model updates until something else resets it. Clear the flag on focus loss as well, and treat the flag as per-field state rather than one shared boolean across the form.
saying these in an interview costs you the question
- Thinks intermediate composition text should be hidden from the control too
- Publishes every intermediate state to the model and its rules
- Writes the bound value back into a control while it is composing
- Assumes each keystroke produces one final character
- Keeps one shared composing flag for every field in the form
- Clears the composing flag only on the end signal, never on focus loss