Engineering Journal
Schema Editor
Schema Editor

Ctrl+Z After Editing a Property Field Does Nothing: The Before-State Timing Bug

2026-06-04

TLDR

When users edit property panel inputs (e.g., changing width from 100 to 250) and press Ctrl+Z, the editor fails to revert the change. This occurs because the undo before-state snapshot was being captured during the change or blur event, after the DOM value had already updated. Capturing before-state during focus ensures the original unmodified value is saved, restoring full undo functionality.
Event TimingCaptured Before-State ValueRestored Undo ValueUser Outcome
change / blur Capture250 (Modified)250Undo does nothing (NO-OP)
focus Capture100 (Original)100Reverts position correctly

Problem statement: the property panel undo defect

After editing an element's coordinate in the inspector panel from 100 to 250, pressing Ctrl+Z leaves the value at 250.

Pressing Ctrl+Z a second time skips the property change entirely and undoes the previous canvas operation.

The history stack contains an entry for "Property Edit", but restoring its before state fails because the recorded before-state value equals the after-state value.


Technical failure mode: input DOM value contamination

HTML form fields update their internal DOM value as users type.

Executing captureState() inside a change event handler reads the updated DOM value:

// DEFECTIVE IMPLEMENTATION: Reading state after DOM modification
$('#prop-x').on('change', function() {
  const before = captureState(); // Reads updated DOM value (250)
  applyToModel(this.value);
  const after = captureState();  // Reads updated DOM value (250)

pushHistory('Property Edit', before, after); // before === after! });


The fix: capture state on focus

Capture propBeforeState when the user focuses the field, before typing begins:

let propBeforeState = null;

// 1. Capture original value on focus $(document).on('focus', '#prop-x, #prop-y, #prop-w, #prop-h', function() { propBeforeState = captureState(); // Reads original value (100) });

// 2. Commit history on change using saved before-state $(document).on('change', '#prop-x, #prop-y, #prop-w, #prop-h', function() { const before = propBeforeState || captureState(); propBeforeState = null;

applyToModel(this.value); const after = captureState();

pushHistory('Property Edit', before, after); });

Rule of thumb: Capture property before-state during the focus event. Never capture before-state inside change or blur handlers where input DOM values are already modified.
Read this post in the full Engineering Journal →