fix(treetable): sync frozen columns vertically when they arrive after init - #1407
Open
rene-schakmann wants to merge 1 commit into
Open
fix(treetable): sync frozen columns vertically when they arrive after init#1407rene-schakmann wants to merge 1 commit into
rene-schakmann wants to merge 1 commit into
Conversation
… init TTScrollableView resolved its frozen sibling once, in ngAfterViewInit. The frozen view is rendered by `*ngIf="frozenColumns || frozenBodyTemplate || _frozenBodyTemplate"`, so when none of those are set on the first render — the ordinary case of `frozenColumns` bound to asynchronously resolved data — the unfrozen view initialised with `frozenSiblingBody` undefined and without the `p-treetable-unfrozen-view` class, and neither was ever re-evaluated. The result was a permanently broken component: `onBodyScroll` guards on `frozenSiblingBody`, so the frozen rows never followed the scrollable rows vertically, while horizontal scrolling kept working because it does not go through that reference. The missing class also dropped `position: absolute; top: 0`, stacking the scrollable view below the frozen view instead of beside it. Resolution now lives in `bindFrozenSiblingBody()` and runs from ngAfterViewChecked as well, so a frozen view that shows up later is picked up. The lookup short-circuits on a still-connected reference, keeping the steady state to a single property read per check. Removing the frozen columns again drops the class and releases the reference. Fixes openng-org#942
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Defect Fix
Fixes #942
Problem
TTScrollableViewresolved its frozen sibling exactly once, inngAfterViewInit:The frozen view is rendered by
*ngIf="frozenColumns || frozenBodyTemplate || _frozenBodyTemplate". When none of those are set on the first render — the ordinary case offrozenColumnsbound to data that resolves asynchronously — the frozen view does not exist yet, so the unfrozen view initializes with:frozenSiblingBodyleftundefined, andp-treetable-unfrozen-viewclass never added.Neither is ever re-evaluated once the frozen view appears, which leaves the component permanently in a broken state:
onBodyScrollguards onif (this.frozenSiblingBody), so the frozen rows never follow the scrollable rows. Horizontal scrolling still works because it does not go through that reference — matching the report exactly..p-treetable-unfrozen-view { position: absolute; top: 0; }never applies, so the scrollable view stacks below the frozen view instead of beside it.Measured on the docs demo with
frozenColumnssupplied asynchronously (Chrome,virtualScrollon,scrollHeight="250px"):unfrozen.scrollTop = 180→frozen.scrollTop0180p-treetable-unfrozen-viewappliedtop195/484(stacked)This also explains the workarounds in the issue thread: every one of them re-attaches the scroll listener from the consumer's own
ngAfterViewInit/ngAfterViewChecked.Solution
Move the resolution into
bindFrozenSiblingBody()and call it fromngAfterViewCheckedas well asngAfterViewInit, so a frozen view that appears later is picked up. The lookup short-circuits onfrozenSiblingBody?.isConnected, so the steady state is a single property read per check — thequerySelectoronly runs while the reference is missing or stale.Removing the frozen columns again is handled symmetrically: the class is dropped and the reference released, so a view that stops being "unfrozen" does not keep a detached node alive.
The selector split between
[data-pc-name="virtualscroller"](virtual scroll) and[data-pc-section="scrollablebody"]is unchanged, and is now also re-evaluated ifvirtualScrollis toggled, since that swaps the body element out.Changes
packages/optimus-ui/src/treetable/treetable.ts— extractbindFrozenSiblingBody(), call it fromngAfterViewChecked, release the reference and class when frozen columns are removedpackages/optimus-ui/src/treetable/treetable.spec.ts— 5 tests covering late-arriving frozen columns (virtual and non-virtual), the unfrozen class, scroll propagation, and teardownVerification
ng test optimus-ui --include='**/treetable/*.spec.ts'→ 179/179 passing (5 new). Fulloptimus-uiunit suite green.Behaviour confirmed in Chrome against the docs TreeTable demo, before and after the change, for both
scrollHeight="250px"andscrollHeight="flex", with and withoutvirtualScroll. The pre-existing synchronous case (frozen columns or a#frozenbodytemplate available on first render) was already working and is unchanged.Breaking Changes
None.
🤖 Generated with Claude Code