Unplanned
Last Updated: 21 Oct 2026 13:59 by ADMIN
Scheduled for 2026 (Nov)
Walter
Created on: 21 Oct 2026 13:31
Category: UI for Blazor
Type: Bug Report
0
Grid does not dispose ColumnDraggable JS instances

Bug report

Reproduction of the problem

Environment

  • Version 15.1.0
  • Blazor Server, .NET 10
  • Chromium (Chrome and Playwright headless)

Grid ColumnDraggable is never destroyed
In Components/Common/Grid/Rows/TableHeaderRow.cs, Dispose() calls base.Dispose() first, which sets IsDisposed = true. It then calls DestroyColumnDraggable(), which uses InvokeAsync<object>. That method returns early when IsDisposed is true (BaseComponent.InvokeAsync<T>), so destroyColumnDraggable is never sent to the browser. DestroyColumnReorderable() and DestroyColumnResizable() work because they use InvokeVoidAsync, which has no such check.

As a result, every grid with Reorderable="true" or Groupable="true" leaves "<dataId>-telerik-ColumnDraggable" in window.TelerikBlazor._instances. Its draggable.element (the grid's .k-grid-header) keeps the whole disposed page reachable, so the page is never garbage collected.

  1. Create two routable pages. Page A has a TelerikGrid with Reorderable="true" and a TelerikTabStrip with a few tabs. Page B is empty.
  2. Open Page A, then navigate to Page B with the in-app router (no full reload).
  3. Run this in the browser console:
Object.entries(TelerikBlazor._instances)
     .filter(([k, i]) => i && i.element && !i.element.isConnected)
     .map(([k, i]) => k + ' / ' + i.constructor.name)

Sample project attached.

TelerikBlazorApp1.zip

Current behavior

(optional)
one "...-telerik-ColumnDraggable" entry per reorderable or groupable grid, all pointing at detached elements. Each pageA -> pageB round trip adds more, and the detached DOM is never released.

Expected/desired behavior

An empty array is returned. Page A's components were disposed, so their JS instances should have been destroyed.

Workaround

After each navigation, we destroy and remove any registered instance whose element is no longer in the page:

   const instances = window.TelerikBlazor && window.TelerikBlazor._instances;
   for (const key of Object.keys(instances || {})) {
       const i = instances[key];
       if (i && i.element && !i.element.isConnected) {
           try { i.destroy && i.destroy(); } catch (e) { }
           delete instances[key];
       }
   }

Suggested Fix

  1. In TableHeaderRow.DestroyColumnDraggable(), use InvokeVoidAsync, as DestroyColumnReorderable() does. Or call the destroy methods before base.Dispose().

Environment

  • Kendo/Telerik version:
  • Browser: [Chrome XX, Firefox]
0 comments