Skip to content

fix(datagrid): write row inspector edits into the rows the grid draws (#2851) - #2858

Merged
datlechin merged 2 commits into
mainfrom
fix/inspector-edit-grid-sync-2851
Sep 15, 2026
Merged

datlechin merged 2 commits into
mainfrom
fix/inspector-edit-grid-sync-2851

Conversation

@datlechin

Copy link
Copy Markdown
Member

Fixes #2851.

The bug

Edit a field in the row inspector and the grid cell beside it keeps the old value. Select another row and come back and the inspector shows the old value too, as if the edit never happened. Save writes it anyway, and the value reappears after the reload. The reporter's recording on the issue shows all three.

Root cause

Two writers of one buffer, and only one of them did the whole job.

The grid's own cell commit, TableViewCoordinator.recordCellEdit, refuses a server-owned column, records the change in DataChangeManager keyed by RowID with that row's own current value as oldValue, writes the new value into the shared TableRows buffer, and repaints the cell.

The inspector's onFieldChanged closure did only the record. TableRows is both what the grid draws from and what MultiRowEditState.configure rebuilds the inspector's fields from, so the edit was invisible in the grid, was dropped from the inspector on the next selection change, and surfaced only when Save wrote the change that had been staged all along.

The fix

The inspector stages a cell edit through the same shape the grid does, in RowEditingCoordinator.stageInspectorFieldEdit: writability gate, one recordCellChange per row with that row's own previous value, one TableRows.editMany, one repaint.

Two things that had to come with it:

  • Rows are named by RowID. MultiRowEditState carried display positions and the commit resolved them when the keystroke arrived, which is the invariant in CLAUDE.md that this pane already shipped once (Faulty Details for Json column #1837). The ids are captured when the selection is configured.
  • The previous value is per row. Every row used to be recorded with one shared value taken from the inspector's field, which is nil, and so NULL, whenever a multi-row selection disagrees on the field.

Undo granularity is unchanged and is left out deliberately. A SwiftUI TextField bound to a string writes its binding per keystroke, so one typed word is still one undo step per character, as it is today. A coalescer was written, reviewed, and cut: making one run of keystrokes one step correctly needs the registered action's destination to track the run, the whole selected row set to stay in it, inserted rows to count as modified, and an editing-session boundary the onFieldChanged callback does not carry. That is its own change, and the evidence is in the report below.

Undo and redo now refresh the inspector as well. handleUndoResult rewrote TableRows and repainted the grid but moved nothing InspectorTrigger watches, so the pane went on showing the value the grid had just taken back. And the inspector's JSON rendering rebuilds when you switch to it, so it cannot show the row as it was before the edit.

The inspector's other writers are untouched: the pickers, Set NULL, Set DEFAULT, Set EMPTY, the SQL functions, the hex editor and the pop-out windows all reach the same MultiRowEditState methods and get the new behaviour for free.

Verification

  • verify.sh build PASS.
  • verify.sh test PASS over InspectorFieldEditStagingTests, DataChangeManagerTests, DataChangeManagerExtendedTests, PendingChangesRowIdentityTests, MultiRowEditStateTests, MultiRowEditStateJsonTests, FieldValueStateTests, AnyChangeManagerTests, ValueFilterEditedRowTests, RowOperationsManagerTests.
  • swiftlint --strict over TablePro TableProTests TableProUITests: no violations in the changed files.
  • New unit suite covers the edit reaching the row buffer, the inspector rebuilding from it, reverting to the stored value clearing the change, undo putting the stored value back, per-row previous values on a multi-row edit, a value filter not moving the edit, a row the buffer no longer holds being skipped, and a server-owned column being refused.
  • New InspectorEditReachesGridUITests types into an inspector field and reads the value back out of the grid's accessibility tree.
  • Negative control: with the row-buffer write removed, 5 of the suite's 8 cases fail. They test the fix rather than passing regardless.
  • Reviewed by Codex (review, working tree). Its findings against the undo coalescer are why that part was cut; the two it raised against the shipped code, the comment style and the docs paragraph, are addressed.

Screenshots

The before state is the reporter's screen recording on #2851. There is no scripted after shot: #2381 made the grid draw its cells with CoreText, so a data-grid row takes no synthetic click from System Events and a screenshot of the edited state cannot be driven without XCUITest. The UI test asserts the same claim a shot would show.

@mintlify

mintlify Bot commented Sep 14, 2026 •

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
TablePro 🟢 Ready View Preview Sep 15, 2026, 12:47 AM

💡 Tip: Enable Automations to automatically generate PRs for you.

Signed-off-by: Ngô Quốc Đạt <datlechin@gmail.com>

This branch was successfully deployed

1 active deployment
staging - docs — 9ca16dc2 Deployed Sep 15, 2026 by mintlify[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cell edit and inspector sidebar edit not redundant

1 participant