While a form's submit request is in flight, what must the form show the user and why disable its submit control?
answer
- submit is a unit of work
- acknowledge, guard, stay honest
- clear it on the failure path too
- disable the control, keep the values
- announce busy, do not only grey out
basics
~10 sIt must show a pending state: the submit control disabled or marked busy, values still on screen, nothing claimed as saved. Without it the user presses again and the same payload is written twice.
solid answer
~40 sA submit is a unit of work with a start, an in-flight period and a settlement, and the form should render all three. When the handler begins I set one pending value for that submission, and the submit control reads it to become disabled and busy-labelled; a live status region announces `Saving…` so the change is not purely visual. The values stay on screen and nothing is cleared or called saved until the response arrives. The pending value must be cleared on a path that also runs when the request rejects or the handler throws — otherwise one failure leaves the form disabled forever. Disabling the control is acknowledgement plus a cheap guard against an impatient second press; it is not a correctness guarantee, because other paths can still start a submission.
go deeper
Know that a submit needs a visible in-flight state and that the submit control is disabled during it. Say out loud that the typed values stay on screen and nothing is called saved until the response comes back.
Explain where the pending value lives, that it is cleared on failure as well as success, and why a framework-tracked submission beats three hand-kept booleans. Mention the accessibility side: a busy state plus an announcement, not just a grey button.
Show the operational cases: a slow request, a rejected one, a thrown handler, a navigation that lands while the request is still open. Say plainly that the disabled control is feedback and that duplicate protection ends on the server.
Frame pending as one submission state shared by every form in the product, so latency behaviour, wording and announcements are consistent. Decide how long a form may sit pending before the UI offers cancel or leave-and-notify.
## What a submission's pending state is A submit is not an instant. It is a **unit of work** with a beginning, an in-flight period, and a settlement that is either a success or a failure. The **pending state** is the part of that unit the interface renders while the work is in flight. It is one value per submission — not one per button, and not a loose collection of booleans scattered across the form. Three jobs sit on it: 1. **Acknowledge.** The user pressed something; the screen must change almost immediately, or they will reasonably conclude nothing happened and press again. 2. **Guard cheaply.** While one write is in flight, the control that started it should not start a second identical one. 3. **Stay honest.** Nothing may read as saved, and no value may be cleared, before the response says so. ## Derive the flag, do not sprinkle it Set the value once as the handler begins, and clear it in a path that also runs when the request rejects **or when the handler throws before the request is even sent**. A pending value cleared only on the success path is the most common bug in hand-rolled submission code: one failure and the form is disabled until a reload. Where the framework tracks an in-flight submission itself — exposing that submission's pending status, its returned result and its error as one tracked thing — prefer it over three hand-kept values. It settles even when the handler throws, and every control that needs the status reads one source instead of being handed the flag down a chain of inputs. How soon a just-written flag can be read back differs by reactivity model. In a runtime that re-runs the component function on each state write, the handler keeps reading the value captured in the run that created it and sees the new one only on the next run. In a fine-grained runtime, the write is visible to the next read straight away. In a compile-time runtime the assignment is rewritten into a notification, but the re-render is still scheduled rather than immediate. That gap does not matter for rendering a spinner; it matters a great deal when you want the flag to also block a second submission inside the same frame. ## What to disable, and what to leave alone - Disable the **submit control**, not every field. A user re-reading what they typed loses focus and context when the whole form goes inert, and in a browser host disabled controls also drop out of the submitted field set — which breaks you badly if you ever fall back to native submission. - Do **not** unmount the control and render something else in its place. Focus is lost, and assistive technology gets a removal rather than a state change. - Keep the control's **accessible name stable**. Add a busy state and, if you like, a visible label change; do not replace text with a bare spinner glyph. - In a browser host, if the disabled control is the form's **default button**, pressing Enter in a text field no longer submits either — a useful side effect, but only for that one path. ## Feedback the disabled attribute does not give you - A **polite live region** that announces `Saving…` and then the outcome. A control flipping to disabled announces nothing by itself. - A **short delay** — a couple of hundred milliseconds — before showing a spinner, so a fast response does not flash. - For genuinely slow work, a line that says so, and a way out (cancel, or leave-and-notify), rather than an indefinite spinner. - **Never clear the values on send.** If the request fails, everything the user typed must still be there. ## Settlement | Outcome | Pending | Values | Errors | Focus | |---|---|---|---|---| | Success, stay on the screen | clear | reset for a create-another flow, keep for an edit and re-baseline what is dirty | clear | leave where it is, announce the result | | Success, navigate away | keep until the next screen commits, so the old form does not flash back to enabled | irrelevant once replaced | clear | move to the new screen's heading | | Failure | clear | keep every value exactly as typed | show the message, per field where you can map it | move to the first offending field or the summary | | Superseded or abandoned | clear for the current submission only | keep | ignore the late response | unchanged | ## The limit of this guard Disabling the control is feedback first and a convenience guard second. It closes the path through that control, and nothing more. Duplicate writes can still arrive from another submission path, from a remount that resets the flag, or from a retry after a lost response — so the correctness story ends at an idempotent write on the server side, not at an attribute in the markup.
- After a successful submit, do you clear the form or keep the values?It depends on what the user does next. A create-another flow resets the fields so the next entry starts clean. An edit form keeps the values — they are now the saved truth — and instead re-baselines its dirty tracking so the form no longer looks unsaved. A one-shot flow replaces the form with a result view entirely. What you never do is clear the fields before the response arrives.
- Why is a submit control that disappears while saving worse than one that stays and goes disabled?Removing it destroys focus, so a keyboard user is dropped back to the document and has to find their place again, and assistive technology hears an element removal instead of a state change. A control that stays, keeps its accessible name and reports a busy state communicates the same thing without moving anyone's cursor. It also keeps the layout from jumping.
- The request fails with a network error rather than a validation error. What does the form do?Clear pending, keep every typed value, and show a form-level message that says the save did not reach the server and can be retried — distinct in wording from a rejection by the server. Leave the submit control enabled again so a retry is one press, and make sure that retry cannot create a second record if the first request actually did land.
It is the shop assistant taking your card and saying "one moment, it is going through" — the acknowledgement is what stops you handing over a second card.
saying these in an interview costs you the question
- Clearing the fields as soon as the request is sent
- Clearing the pending flag only on the success path
- Disabling every field, not just the submit control
- Treating a disabled button as a correctness guarantee
- Showing a spinner with no announcement for assistive technology
- Marking the screen as saved before the response arrives