Autofill or code sets a bound field's value and the model never updates: why does the binding miss it, and what do you do?
answer
- a binding is told, never watching
- property assignment dispatches nothing
- silence prevents the write-back loop
- paste fires, a code write does not
- reconcile at commit and at submit
basics
~20 sAssigning a control's value from code sets the property without dispatching an edit event, and a binding only learns from events. The control and the model then disagree, and a payload built from the model sends the stale value.
solid answer
~50 sA binding is told, never watching: it subscribes to one host event and writes the model when that fires. A **property assignment dispatches nothing** — by design, since otherwise the framework's own write-back would loop straight back in. So anything that fills a field by assigning its value leaves the screen showing one value and the model holding another, and a payload built from state ships the stale one. Real edits are safe: a paste and a drop of text do fire the per-edit event. The unsafe writers are your own code, a manager or extension assigning the property directly, and form restoration after a back navigation; browsers also vary in what they dispatch for their own autofill. Fixes: make the model the only writer; where a third party writes, reconcile by re-reading the control at commit and at submit; and when you must write a control directly, dispatch a synthetic edit event.
go deeper
Remember that a binding learns about changes only from events, so setting a field's value in code leaves the model holding the old value.
Explain why the platform stays silent on a property write — it would loop with the framework's own write-back — and which writers do fire an event, such as a paste.
Diagnose the divergence from the symptom: a filled form that submits the previous value. Then give the remedy ladder and say which side you treat as authoritative at submit.
Set the rule for the codebase: one writer per field, a defined reconcile point, and a sanctioned escape hatch for third-party controls, so this is not rediscovered per form.
## Why nothing fires Host events model **user intent**. A change made by code is not user intent, so assigning a control's value property updates the control and dispatches no edit event. That is not an oversight — it is what keeps bindings from looping. The framework's own downward write-back is itself a property assignment; if assignments fired the per-edit event, every render would look like a fresh user edit and feed straight back into the model. The consequence is the rule to carry: **a binding knows only what an event told it.** The element's property is not the model's source of truth, and nothing keeps them in step except events and the framework's own write-back. ## Who writes a value that is not a keystroke | Writer | Dispatches an edit event? | Binding learns? | |---|---|---| | typing | yes, per edit | yes | | paste, drag-and-drop of text | yes, as an ordinary edit | yes | | your code assigning the value property | no | no | | a manager or extension assigning the property | no | no | | the browser's own autofill | varies by browser and flow | do not rely on it | | form restoration on back navigation or reload | values restored without edit events | no | Two entries deserve care. **Paste is safe** — it is an ordinary edit and the per-edit event carries it, though a commit-source binding still waits for blur. And **autofill is genuinely inconsistent**: modern browsers generally do dispatch an edit event for their own fill, but flows differ and a credential manager that writes the property directly dispatches nothing at all. Treat a filled field as possibly unannounced rather than assuming either behaviour. ## The two shapes of the bug - **The model is stale.** The control shows the filled value, the model holds the old one. The user sees a complete form, presses submit, and the server receives the value from before the fill — or an empty string, which is the version that gets filed as *autofill does not work with our form*. - **The control is stale.** The model changed but the downward write-back did not reach the control, or reached it and was immediately overwritten by a silent third-party write. The user is looking at a value the application no longer holds. Which one you get depends on the reactivity model. A runtime that **re-asserts the bound value on every render** will eventually clobber the silent fill and restore the model's value — destructive, but at least visible. A runtime that writes downward **only when the model value changes** has no reason to write at all, so the two sides can disagree indefinitely and only submit reveals it. ## What to do, in order 1. **One writer.** Route every programmatic change through the model and let the binding render it. Most instances of this bug are code reaching for the control because reaching for the model was awkward. 2. **Reconcile where you cannot control the writer.** On the commit event and again when the payload is assembled, read the control's current value and treat it as authoritative over the model. Building the payload from the live form (`FormData` over the form element) rather than from state makes the whole class disappear for submission, at the cost of doing coercion there. 3. **Dispatch a synthetic edit event** after any unavoidable direct write, so the binding and every other listener converge on the same value. This is the only safe way to hand a value to a control you do not own. 4. **Re-read at mount and on first focus.** Restored and pre-filled values are already in the controls before your code runs; a read at mount closes that gap, and a reconcile on first focus catches a fill that arrived later. 5. **Use the host's own signal where one exists.** Platforms expose a way to tell that a field was filled rather than typed; using it to trigger a reconcile beats polling. ## The trap to avoid Do not solve this by polling the control on a timer or by diffing on every animation frame. It burns work on every field forever to catch an event-less write that a reconcile-on-commit already catches, and it reintroduces the loop the platform avoided: a poll cannot distinguish the framework's own write-back from a third party's. ## How to answer this in an interview State the mechanism first — property assignment dispatches no event, and a binding only learns from events — then show you know the boundary: paste and drag-and-drop *do* fire, autofill varies, a manager writing the property does not. Then give the remedy ladder: single writer, reconcile at commit and submit, synthetic event as the escape hatch. Saying *the element is not the source of truth, and neither is the model unless something keeps them in step* is the sentence that lands.
- Why does the platform deliberately not dispatch an edit event for a programmatic write?Because the framework's own downward write-back is a programmatic write. If assignments dispatched the per-edit event, every render would look like a fresh user edit, feed back into the model and re-render — an unbounded loop. Silence is what makes two-way binding terminate.
- Your team fixes the autofill bug by building the submit payload from the live form controls. What did that just move rather than solve?Coercion and shape. The controls give strings, file handles and checked flags, so the payload layer now owns parsing, empty-versus-absent and any field that has no control at all. It removes the staleness class for submission only — anything else deriving from the model is still reading a value that never arrived.
- You must hand a value to a third-party control you do not own. What is the safe procedure?Write the value, then dispatch the edit event the control's own bindings listen for, and the commit event if listeners depend on it. That makes your write indistinguishable from a user edit for every subscriber, instead of only for the one path you tested.
saying these in an interview costs you the question
- Believes assigning a control's value notifies the binding
- Says a paste is invisible to a per-edit binding
- Assumes every browser dispatches an edit event for autofill
- Treats the control's property as the source of truth without reconciling
- Polls every field on a timer to catch silent writes
- Blames autofill for not working instead of the event-less write