Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/Components/Web.JS/src/Virtualize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ function findClosestScrollContainer(element: HTMLElement | null): HTMLElement |
}

function init(dotNetHelper: DotNet.DotNetObject, spacerBefore: HTMLElement, spacerAfter: HTMLElement, rootMargin = 50): void {
// If the component was disposed before the JS interop call completed, the element references may be null.
// In this case, we should return early to avoid errors.
if (!spacerBefore || !spacerAfter) {
return;
}

// Overflow anchoring can cause an ongoing scroll loop, because when we resize the spacers, the browser
// would update the scroll position to compensate. Then the spacer would remain visible and we'd keep on
// trying to resize it.
Expand Down Expand Up @@ -66,6 +72,11 @@ function init(dotNetHelper: DotNet.DotNetObject, spacerBefore: HTMLElement, spac
// and reobserving spacers when they get resized, the intersection callback will re-run if they remain visible.
const observerOptions = { attributes: true };
const mutationObserver = new MutationObserver((mutations: MutationRecord[], observer: MutationObserver): void => {
// Check if the spacer is still in the DOM
if (!spacer.isConnected) {
return;
}

if (isValidTableElement(spacer.parentElement)) {
observer.disconnect();
spacer.style.display = 'table-row';
Expand All @@ -87,6 +98,11 @@ function init(dotNetHelper: DotNet.DotNetObject, spacerBefore: HTMLElement, spac
return;
}

// Check if the spacers are still in the DOM. They may have been removed if the component was disposed.
if (!spacerBefore.isConnected || !spacerAfter.isConnected) {
return;
}

// To compute the ItemSize, work out the separation between the two spacers. We can't just measure an individual element
// because each conceptual item could be made from multiple elements. Using getBoundingClientRect allows for the size to be
// a fractional value. It's important not to add or subtract any such fractional values (e.g., to subtract the 'top' of
Expand Down
Loading