LearnNewsExamplesServices
Frontmatter
id9483
titleGrid: Implement Reactive locked Config and Run-Time Column Reordering
stateClosed
labels
enhancementaigrid
assigneestobiu
createdAtMar 16, 2026, 12:10 PM
updatedAtMar 16, 2026, 12:31 PM
githubUrlhttps://github.com/neomjs/neo/issues/9483
authortobiu
commentsCount1
parentIssue9456
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMar 16, 2026, 12:31 PM

Grid: Implement Reactive locked Config and Run-Time Column Reordering

Closed v12.1.0 enhancementaigrid
tobiu
tobiu commented on Mar 16, 2026, 12:10 PM

This is a sub-task of Epic #9456 (Buffered Grid - High-Performance Locked Columns).

Context: To support locking columns dynamically at run-time (e.g., from a context menu) or restoring saved grid states, the locked configuration needs to be fully reactive. This requires a robust architectural pipeline to ensure all layers of the Grid (the columns collection, header.Toolbar items, layout engine, and Body VDOM) stay perfectly synchronized without memory leaks or tearing.

Implementation Plan:

  1. grid.column.Base:

    • Add a reactive locked_ config ('start' | 'end' | null).
    • Implement afterSetLocked(value, oldValue). If oldValue !== undefined, trigger this.parent.onColumnLockChange(this).
  2. grid.header.Button:

    • Ensure the button receives the locked value and updates its CSS classes (e.g., neo-locked-start).
  3. grid.Container:

    • Extract the sorting logic from createColumns() into a reusable sortColumns(columnsArray) method.
    • Implement onColumnLockChange(column).
      • Re-sort the physical me.columns array using sortColumns().
      • Re-sort the headerToolbar.items array to match the new column order (without destroying/recreating instances).
      • Call headerToolbar.passSizeToBody(false) to trigger the mathematical layout recalculation.
  4. grid.Body:

    • After a column reorder, the VDOM must be fully regenerated to ensure cell pooling correctly projects the new column order and X-coordinates into the visible cells.
    • Ensure the layout pipeline gracefully cascades into body.createViewData() to re-render the visible rows.
tobiu added the enhancement label on Mar 16, 2026, 12:10 PM
tobiu added the ai label on Mar 16, 2026, 12:10 PM
tobiu added the grid label on Mar 16, 2026, 12:10 PM
tobiu assigned to @tobiu on Mar 16, 2026, 12:10 PM
tobiu added parent issue #9456 on Mar 16, 2026, 12:10 PM
tobiu referenced in commit b7bf06e - "Grid: Implement Reactive locked Config and Run-Time Column Reordering (#9483)" on Mar 16, 2026, 12:30 PM
tobiu
tobiu Mar 16, 2026, 12:30 PM

Input from Gemini 3.1 Pro:

✦ I have completed the implementation for this sub-task (#9483).

Changes Implemented:

  1. grid.column.Base: Added the reactive locked_ config ('start', 'end', null) and implemented afterSetLocked() to trigger parent.onColumnLockChange(this).
  2. grid.header.Button: Added the reactive locked_ config and implemented afterSetLocked() to dynamically update the neo-locked-start and neo-locked-end CSS classes.
  3. grid.Container:
    • Extracted column sorting logic into the sortColumns(columnsArray) method for reusability.
    • Implemented onColumnLockChange(column) which handles the synchronization pipeline.
    • Used the Container API moveTo() inside a silentVdomUpdate block to bulk-reorder the header buttons cleanly without destroying instances.
    • Re-ordered the me.columns collection cleanly using clearSilent() and add() to avoid triggering redundant mutate events that would otherwise ping-pong the aria-colcount.
    • Called headerToolbar.passSizeToBody(false) to mathematically recalculate logical X coordinates.
    • Explicitly called me.body.createViewData() at the end of the pipeline to trigger a full row/cell re-render, ensuring the new column order and styles are immediately reflected in the viewport via the cell pooling engine.
tobiu closed this issue on Mar 16, 2026, 12:31 PM
tobiu cross-referenced by #9460 on Mar 16, 2026, 1:22 PM