feat(template): add visibleRange output to rx-virtual-scroll-viewport - #1940
Draft
hoebbelsB wants to merge 2 commits into
Draft
feat(template): add visibleRange output to rx-virtual-scroll-viewport#1940hoebbelsB wants to merge 2 commits into
hoebbelsB wants to merge 2 commits into
Conversation
`viewRange` reports the range rendered to the DOM, which every scroll strategy deliberately widens by the runway items and, when `appendOnly` is enabled, by everything that has ever been rendered. That keeps its `start` at 0 for the entire lifetime of an appendOnly list, so it can't be used to figure out where the user actually is. Add a second output, `visibleRange`, emitting the range of items intersecting the viewport - `start` is the index of the first, `end` the exclusive index of the last intersecting item. All three built-in strategies compute it right next to their rendered range, before the appendOnly widening kicks in. On `RxVirtualScrollStrategy` it defaults to `renderedRange$`, so third party strategies keep working unchanged. Closes #1865
…m from visibleRange `visibleRange.end` unconditionally added 1 to `lastScreenItem.index`, so an item whose top edge lands exactly on the bottom edge of the viewport was reported as visible although none of it is. The tests could not detect this because the expectation helper reimplemented the production formula; they now derive the expected range independently.
|
View your CI Pipeline Execution ↗ for commit 97cd718
💡 Dealing with memory or CPU issues? See memory and CPU details with the resource usage add-on ↗. ☁️ Nx Cloud last updated this comment at |
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.
What
Adds a second range output to
rx-virtual-scroll-viewport:visibleRangeemits the range of items intersecting the viewport:startis the index of the first,endthe exclusive index of the last intersecting item. Partially visible items count. It is never widened byrunwayItems,runwayItemsOppositeorappendOnly.viewRangeis unchanged.Why
Closes #1865.
viewRangedocuments itself as "the range of items being actually rendered to the DOM", and the strategies deliberately widen it:With
appendOnlythat pinsviewRange.startto0forever, which is correct for the rendered range but leaves consumers with no way to tell where the user actually is — the blocker for lazy loading described in the issue. Per the discussion in #1865, the fix is a second output rather than a change toviewRange.How
RxVirtualScrollStrategy(@publicApi) gets a concrete, overridableget visibleRange$()that returnsrenderedRange$. It is deliberately not abstract, so existing third-party strategies keep compiling and keep emitting; they simply fall back to the old behaviour until they opt in.map()as the rendered range, before theappendOnlywidening:{ start: anchorItem.index, end: min(length, lastScreenItem.index + 1) }scrollTopand the visible container size, reusing the existingscrolledIndexexpression forstartstartis intentionally the same value as the existingscrolledIndexChange, which is already defined as "the topmost item actually being visible".Tests
npx nx component-test template— a newdescribe('visibleRange')block in each of the three specs (fixed-size, dynamic-size, autosize):visibleRange.startwhile scrolling withappendOnly=true— the appendOnly=true Behavior in AutoSizeVirtualScrollStrategy Causes viewRange.start to Always Be 0 #1865 regression: assertsviewRange.startis still0(unchanged, documented behaviour) whilevisibleRange.startfollows the viewportvisibleRange.starttracksscrolledIndexChangecontainerHeightchangesPlus a unit assertion that a strategy which does not override
visibleRange$still emits, proving the new member is non-breaking.Verified the tests are real: with only the three strategy implementations reverted (model/viewport/tests intact), 4 tests fail per spec with e.g.
expected visibleRange to have been called with arguments {start: 100, end: 106}, and every pre-existing test still passes.71/71 component tests, 659 jest tests and
nx lint template(0 errors) pass with the change.Docs
visibleRangerow added to the outputs table inrx-virtual-scroll-viewport.mdappendOnlyrow inrx-virtual-scroll-strategies.mdRepair
A review of the first commit found blocking defects. Addressed in the follow-up commit:
Off-by-one in
visibleRange.end. It unconditionally added 1 tolastScreenItem.index, so an item whose top edge landed exactly on the bottom edge of the viewport was reported as visible although none of it is. Fixed in both the autosize and dynamic-size strategies vialastScreenItem.index + (lastScreenItem.offset > 0 ? 1 : 0).The original tests could not have caught this: the expectation helper reimplemented the production formula, so it agreed with the bug. The tests now derive the expected range independently.
Verification
Cypress component tests: 78 specs, all passing (
nx component-test template). Lint: 0 errors.Open questions
nx build-lib templatecould not be verified here: the target shells out toyarn tsc -p libs/cdk/tsconfig.schematics.jsonand yarn fails inside the git worktree with "Couldn't find the node_modules state file". This is an environment limitation of the worktree, not a regression — the public API was instead typechecked withnpx tsc -p libs/template/tsconfig.lib.json --noEmit, which reports only one pre-existing error inlibs/template/virtual-view/src/lib/tests/test-utils/testbed.tsthat is also present on the untouched baseline.visibleRangealso be surfaced in the how-to pageapps/docs/docs/packages/template/how-to/virtual-scroll-recipes.md? Its infinite-scroll recipe currently drives loading offviewRange/scrolledIndexChangeand would arguably be better written againstvisibleRange, but rewriting a recipe felt out of scope for a bug fix — left for the maintainer to decide.autosize'srenderedRange$is a plainSubjectwhile the other two useReplaySubject(1). The new_visibleRange$is aReplaySubject(1)in all three for consistency, so a late subscriber to autosize'svisibleRangegets the current range whereas a late subscriber toviewRangedoes not. That asymmetry seemed like the more useful behaviour, but it is a deliberate difference worth a maintainer's eye.