Skip to content

feat(tree): add trackBy to tree controls to keep the expansion of rebuilt nodes (#DS-5785) - #2253

Open
nazirgitwork wants to merge 4 commits into
koobiq:mainfrom
nazirgitwork:feat/DS-5785-tree-track-by
Open

nazirgitwork wants to merge 4 commits into
koobiq:mainfrom
nazirgitwork:feat/DS-5785-tree-track-by

Conversation

@nazirgitwork

Copy link
Copy Markdown

Summary

A tree control tracks expansion by node identity, so with KbqTreeFlatDataSource (or any source that rebuilds its node objects when the data changes) every expanded node comes back collapsed after a data update, and every row is re-created.

FlatTreeControl and NestedTreeControl now accept an optional trackBy in a new last options argument. With it, expansionModel holds the node keys instead of the nodes, so expansion survives a rebuild. The tree also falls back to the control's trackBy to re-use row views when its own trackBy input is not set. Without the option, behaviour is unchanged: the key type K defaults to the node type.

List of notable changes:

  • added trackBy and the KbqTreeControlOptions<T, K> options argument to FlatTreeControl and NestedTreeControl. Expand, collapse, expandAll, filtering, and state saving/restoring go through the key.
  • added the key type parameter K = T to TreeControl, BaseTreeControl, KbqTreeFlatDataSource, KbqTreeSelection and its event classes, and KbqTreeSelect, so a typed query or event can name the key type (KbqTreeSelection<Node, string>).
  • updated KbqTreeBase: its trackBy input now defaults to the control's trackBy, and the bound on the control type leaves out expansionModel, so controls with any key type are accepted.
  • fixed FlatTreeControl.getDescendants and getParents for a node rebuilt since the last data update: with trackBy it is found by its key.
  • fixed the toggle icon state when kbqTreeNodeToggle has no [node] binding: it now reads the same node toggle() acts on.
  • fixed keyboard navigation order in kbq-tree-selection after re-used rows change order: the rendered options are re-sorted when only their order changed.
  • updated the tree documentation (en/ru) with the control trackBy and how it relates to the tree's own trackBy input.

What should reviewers focus on?

  • Typing: expansionModel becomes SelectionModel<K>. K defaults to T, so existing code compiles unchanged, as the unchanged API reports of the other entry points show. The filter-bar report changes only because the defaulted K is now written out.
  • KbqTreeBase<T, C extends Omit<TreeControl<T>, 'expansionModel'>>: SelectionModel<K> makes a control invariant in K, so keeping expansionModel in the bound would reject controls with a trackBy.
  • State saving with trackBy (tree-base.ts): keys can't be turned back into values, so the saved state is collected from the current dataNodes.
  • renderedOptionsOutOfOrder() in tree-selection.component.ts: the options query doesn't emit when re-used rows only move.

@github-actions github-actions Bot added the enhancement New feature or request label Oct 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant