Frontmatter
| id | 9448 |
| title | TreeGrid Component pooling accumulates `is-leaf` class leading to visual bugs |
| state | Closed |
| labels | bugaigrid |
| assignees | tobiu |
| createdAt | Mar 12, 2026, 12:29 PM |
| updatedAt | Mar 12, 2026, 12:31 PM |
| githubUrl | https://github.com/neomjs/neo/issues/9448 |
| author | tobiu |
| commentsCount | 1 |
| parentIssue | 9404 |
| subIssues | [] |
| subIssuesCompleted | 0 |
| subIssuesTotal | 0 |
| blockedBy | [] |
| blocking | [] |
| closedAt | Mar 12, 2026, 12:31 PM |
TreeGrid Component pooling accumulates is-leaf class leading to visual bugs
tobiu assigned to @tobiu on Mar 12, 2026, 12:30 PM
tobiu added parent issue #9404 on Mar 12, 2026, 12:30 PM

tobiu
Mar 12, 2026, 12:31 PM
Input from Gemini 3.1 Pro:
✦ The bug was diagnosed and fixed. The issue was that
updateIconCls()insrc/grid/column/component/Tree.mjswas using.push()on theclsarray inside multipleafterSet...hooks. During rapid state changes (e.g. Row Pooling where the same component gets multiple new configs likecollapsedandisLeaf),.push()accumulated multiple instances of the state classes. Later,NeoArray.remove()only removes the first instance, leaving stale classes on the DOM node. Replacing.push()withNeoArray.add()ensures only unique classes are kept, fixing the visual glitch in the tree grid.Test
test/playwright/e2e/GridTree.spec.mjsnow passes successfully.
tobiu closed this issue on Mar 12, 2026, 12:31 PM
tobiu cross-referenced by #9412 on Mar 12, 2026, 12:41 PM
Description
In
Neo.grid.column.component.Tree, theupdateIconCls()method mutates the class array usingcls.push('is-leaf')inside multipleafterSet...hooks (e.g.afterSetIsLeaf,afterSetCollapsed, etc). When multiple configs change simultaneously (e.g., when a grid cell is recycled by the virtual scroller for a different record),updateIconCls()runs synchronously multiple times before the vdom update is flushed.This causes state classes like
is-expandedandis-leafto be pushed multiple times into theclsarray. Later, when the component is recycled again,NeoArray.remove()only removes the first instance of these duplicate classes. This leads to conflicting classes persisting on the DOM node (e.g.<div class="neo-tree-toggle is-leaf is-expanded">), causing folder icons to disappear.Solution
Use
NeoArray.add(cls, ...)instead ofcls.push(...)inTree.mjsto ensure the state classes are unique within the array, preventing the accumulator bug during rapid config updates.