Skip to content

Grid inside TreeGrid row details: clicking row triggers unwanted scrollIntoView jump to bottom #10823

@ysnbytrk

Description

@ysnbytrk

Describe the bug

When using a vaadin-grid inside the row details (expanded rows) of a parent vaadin-grid (tree structure), clicking on a row in the inner grid causes the page to unexpectedly scroll/jump to the bottom of the page.

Architecture

Our application has a nested grid structure:

  1. Outer TreeGrid (vaadin-grid#synchronization-tree-grid) - displays calendar weeks as expandable tree nodes
  2. Row Details Content - when a week is expanded, it renders an inner grid
  3. Inner Grid (vaadin-grid inside rtt-planning-order-grid custom element) - displays planning orders with all-rows-visible attribute
synchronization-view
└── synchronization-tree (vaadin-grid with tree toggle)
    └── row-details (when expanded)
        └── rtt-planning-order-grid (custom element)
            └── vaadin-grid (with all-rows-visible)

The Problem

When a user clicks on any row in the inner grid (to select it or open row details), the browser scrolls to the bottom of the page. We suspect this is related to Vaadin's grid internally calling scrollIntoView() on the selected element, but in this nested structure, it causes unexpected scroll behavior.

Current Workaround

We had to implement a complex workaround that:

  1. Temporarily overrides Element.prototype.scrollIntoView to a no-op function
  2. Saves scroll position before any grid interaction
  3. Restores scroll position after grid operations complete
  4. Uses custom events (block-scroll-into-view, restore-scroll-position) to coordinate between components

This workaround is fragile, affects global prototypes, and shouldn't be necessary.

Related Code from workaround

// In synchronization-tree.ts - we had to override scrollIntoView globally
private _blockScrollIntoView(): void {
    if (this._isScrollBlocked) return;
    this._isScrollBlocked = true;
    this._originalScrollIntoView = Element.prototype.scrollIntoView;
    this._saveScrollPosition();

    // Override scrollIntoView to do nothing
    Element.prototype.scrollIntoView = function() {
        // Do nothing - blocked
    };
}
// In rtt-planning-order-grid.ts - active-item-changed handler
@active-item-changed="${(event: GridActiveItemChangedEvent<PlanningOrder>) => {
    // Save scroll position before any DOM changes
    const scrollY = window.scrollY;
    const scrollX = window.scrollX;

    this.detailsOpenedItem = order ? [order] : [];

    // Restore scroll position after resize
    requestAnimationFrame(() => {
        if (this.grid) {
            (this.grid as any).notifyResize?.();
        }
        window.scrollTo(scrollX, scrollY);
    });
}}"

Expected-behavior

When clicking on a row in an inner grid (nested inside row details of a parent tree grid):

  1. The row should be selected/activated without any page scroll
  2. If the inner grid has all-rows-visible attribute, it should not trigger any scrollIntoView behavior
  3. Row details expansion in the inner grid should not cause scroll jump
  4. The grid should respect the current scroll position and not modify it unexpectedly

The scroll position should remain unchanged when interacting with nested grids.

Reproduction

Steps to Reproduce:

  1. Create a parent vaadin-grid configured as a tree (with expandable rows)
  2. Use gridRowDetailsRenderer to render an inner vaadin-grid when rows are expanded
  3. Set all-rows-visible attribute on the inner grid
  4. Have enough content that the page is scrollable
  5. Scroll down to middle of the page
  6. Click on the toggle to expand a tree row (showing the inner grid)
  7. Click on any row in the inner grid

Expected: The row is selected, page scroll position remains the same
Actual: The page jumps/scrolls to the bottom

Minimal Reproduction Structure:

<!-- Outer tree grid -->
<vaadin-grid id="tree-grid"
             .dataProvider=${treeDataProvider}
             .expandedItems="${expandedItems}"
             ${gridRowDetailsRenderer(this.renderRowDetails)}>
    <vaadin-grid-column path="name"
        ${columnBodyRenderer(this.treeToggleRenderer)}>
    </vaadin-grid-column>
</vaadin-grid>

<!-- Row details renderer returns -->
<vaadin-grid all-rows-visible
             @active-item-changed="${this.onInnerRowClick}">
    <!-- inner grid columns -->
</vaadin-grid>

System Info

  • Operating System: Windows 10/11
  • Vaadin Version: 24.7.1
  • Vaadin Grid Version: 24.7.1
  • Hilla Version: 24.7.1
  • Browser: Latest stable versions of Chrome, Edge, Firefox
  • Build Tool: Maven + Vite 6.2.3
  • TypeScript: 5.7.3
  • Lit: 3.2.1

Note: This is a Vaadin Hilla application (not Flow), using Lit-based web components.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions