vuetifyjs / vuetifyjs/vuetify

[Feature Request] v-data-table-virtual: Expose scroll container element or an @scroll-end event for infinite scroll use cases

Open
#22,647 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

C: VDataTableVirtual T: feature
Dominant language
TypeScript
Stars
41k
Forks
7.1k
Avg merge
1d 21h
Merged PRs (30d)
11

Description

Problem to solve

Thank you for the excellent work on v-data-table-virtual. I'm implementing infinite scroll (cursor-based pagination) with this component and ran into a limitation I'd love to see addressed.

v-data-table-virtual manages its own internal scroll container (.v-table__wrapper), but this element is not accessible through any public API. The #bottom slot renders outside the scroll container, so an IntersectionObserver placed there always fires because the element is always visible in the browser viewport.

The only way to implement reliable scroll-to-bottom detection currently is to reach into the component internals via querySelector('.v-table__wrapper') and either:

  • attach a manual scroll event listener, or
  • use it as the root of an IntersectionObserver (combined with a sentinel in #tfoot, which does render inside the scroll container)

Both approaches depend on the internal class name .v-table__wrapper, which is not part of the public API and could change at any time.

Proposed solution

Proposed solutions (any one would suffice)

  1. Expose a scrollerRef / containerRef (https://github.com/vuetifyjs/vuetify/blob/e83fa8822633aeb09dfe332e51d6ae84726bf5e8/packages/vuetify/src/components/VDataTable/VDataTableVirtual.tsx#L212) — a template ref pointing to the scroll container element, similar to how VVirtualScroll exposes things internally. This would allow users to attach their own observers or listeners cleanly.

  2. Emit a @scroll-end (or @load-more) event — fired when the user has scrolled near or to the bottom of the content. A threshold prop (e.g. :load-more-threshold="200") would make this flexible.

  3. A dedicated #load-more or #scroll-end slot — rendered inside the scroll container at the bottom of the content, so an IntersectionObserver without a custom root would work correctly out of the box.

Current workaround

// Fragile: depends on internal class nameconst scrollWrapper = tableEl.querySelector('.v-table__wrapper')observer = new IntersectionObserver(callback, { root: scrollWrapper })observer.observe(sentinelInTfoot)

This works today but is brittle. Any of the proposed additions would allow this to be implemented cleanly without relying on internals.

Thank you for considering this!
I can propose a PR with a solution like mentioned above (e.g. Expose a scrollerRef / containerRef).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/vuetify/src/components/VDataTable/VDataTableVirtual.tsx at the referenced line and compare how VVirtualScroll exposes its internal scrolling behavior. Reproduce the current .v-table__wrapper workaround and evaluate the proposed ref, event, and slot approaches. Done means users can detect scroll-to-bottom without querying the internal class name.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.