webdevpuneet.com

Form Change Diff Preview — Confirm Exactly What Will Change Before Saving

Form Change Diff Preview — Show Exactly What Will Change Before Saving · Forms · Plain HTML, CSS & JS · Live preview

CategoryForms

Copy & paste

Source Code

<div class="demo">
  <form id="settingsForm" class="settings-form">
    <div class="f-row">
      <label for="fName">Display name</label>
      <input id="fName" name="name" type="text" value="Alex Rivera" />
    </div>
    <div class="f-row">
      <label for="fEmail">Email</label>
      <input id="fEmail" name="email" type="email" value="[email protected]" />
    </div>
    <div class="f-row">
      <label for="fRole">Role</label>
      <select id="fRole" name="role">
        <option value="viewer">Viewer</option>
        <option value="editor" selected>Editor</option>
        <option value="admin">Admin</option>
      </select>
    </div>
    <div class="f-row f-checkbox">
      <label><input type="checkbox" id="fNotify" name="notify" checked /> Email notifications</label>
    </div>

    <button type="submit" class="save-btn" id="saveBtn" disabled>No changes to save</button>
  </form>

  <div class="diff-panel" id="diffPanel" hidden>
    <h3>Review changes</h3>
    <ul class="diff-list" id="diffList"></ul>
    <div class="diff-actions">
      <button type="button" class="btn ghost" id="cancelDiff">Keep editing</button>
      <button type="button" class="btn primary" id="confirmDiff">Confirm &amp; save</button>
    </div>
  </div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Computes a genuine field-by-field diff against a snapshot of the form's original values
Correctly handles checkboxes, which FormData omits entirely when unchecked
Save button live-updates its label with an exact change count and disables itself when there is nothing to save
Confirmation panel shows old value struck through next to the new value for every changed field
Diff-friendly value formatting layer separates raw form values from what is actually displayed
Confirming a save correctly updates the baseline so a second edit cycle diffs against the latest saved state
Keep-editing cancel path leaves the form untouched and simply closes the review panel

About this UI Snippet

Form Change Diff Preview — Reviewable Confirmation Before You Save

Screenshot of the Form Change Diff Preview — Show Exactly What Will Change Before Saving snippet rendered live

Most settings forms save silently — click submit, and whatever the form currently contains overwrites whatever was there before, with no chance to review exactly what changed. That's fine for a single text field, but risky for a form with several fields where a user might not remember which value they actually edited. This snippet computes a genuine diff between the form's original state and its current state, and only lets the save proceed after showing that diff for confirmation.

Snapshotting the baseline once, correctly

snapshotForm() runs exactly once, when the page loads, and captures every field's value into a plain object using FormData. The one non-obvious detail: FormData omits unchecked checkboxes entirely — an unchecked box simply doesn't appear as an entry — so the snapshot function explicitly reads form.notify.checked and records 'on'/'off' itself rather than trusting FormData to represent that field's absence-or-presence correctly. Get this wrong and an unchecked-then-rechecked box would never show up in the diff at all.

Diffing is deliberately dumb — and that's the point

computeDiff() does nothing clever: it loops over every key in the original snapshot and does a strict string comparison against the current value. There's no fuzzy matching, no attempt to interpret *meaning* — just "is this exact string different from that exact string." For a confirmation UI whose entire job is to be trustworthy, predictable beats clever; a user reviewing a diff needs to know it reflects reality with zero ambiguity.

The Save button as a live change counter

refreshSaveButton() runs on every input and change event, recomputing the diff and updating the button's label to read "Save 2 changes" or disabling it entirely back down to "No changes to save" the moment a user reverts a field back to its original value. This means the button is never a lie — if it says "no changes," there genuinely are none, and if it's disabled, submitting is correctly impossible rather than merely discouraged.

Confirming applies the new baseline, not just closes the panel

When the user clicks Confirm & save, the code doesn't just hide the diff panel — it calls Object.assign(originalValues, currentValues()), replacing the baseline with the just-saved values. This matters: without it, a second edit-and-save cycle would incorrectly diff against the *original* pre-first-save values instead of the form's actual last-saved state, showing changes that were already committed as if they were still pending.

Step by step

How to Use

  1. 1
    Edit one or more fieldsThe Save button updates live, counting how many fields differ from their original values and disabling itself entirely when nothing has changed.
  2. 2
    Click SaveInstead of submitting immediately, a diff panel opens showing every changed field with its old value struck through next to the new value.
  3. 3
    Review the diffEach row is field-by-field — exactly what will change, nothing summarized or hidden. Revert manually in the form if something looks wrong.
  4. 4
    Confirm or keep editingConfirm & save applies the change (wire your real API call into the confirmDiff click handler) and resets the baseline; Keep editing closes the panel without saving.
  5. 5
    Adapt the field listUpdate FIELD_LABELS and formatValue() to match your own form's fields and how each value should be displayed in the diff.

Real-world uses

Common Use Cases

ADMIN
Account & team settings forms
Let admins confirm exactly what will change before updating a user's role, email, or permissions — reduces accidental overwrites.
Multi-field profile editors
Any settings page with several independent fields benefits from a clear, reviewable summary before committing.
AUDIT
Change-sensitive configuration
Config panels where a wrong save is costly (billing settings, infra config) benefit from an explicit review step.
UX
Reducing accidental saves
Disabling Save entirely when nothing changed prevents no-op network requests and confusing "saved" toasts for identical data.
Related: Natural Language Date Input — Type
See the Natural Language Date Input — Type for a related forms pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

FormData only includes checked checkboxes as entries — an unchecked box is simply absent from the FormData object rather than present with a false value. Reading form.notify.checked directly and recording "on"/"off" explicitly avoids silently losing that field from the diff.

The diff recomputes on every input/change event, so a reverted field simply drops out of the change list — if every field is reverted, the Save button disables itself again automatically.

The confirmDiff click handler is where you'd wire in your real API call. As written it updates the local baseline snapshot to simulate a successful save, so a second round of edits diffs correctly against the just-saved state.

Yes — add the field to FIELD_LABELS with its display name, and to formatValue() if it needs special formatting (like the role and notify fields do). The diff and snapshot logic already iterate generically over every field.

A confirmation UI needs to be exactly trustworthy — if it says a field changed, it must genuinely differ, byte for byte. Fuzzy comparisons would risk either hiding a real change or flagging a non-change, undermining the entire point of a review step.