Custom Views: Prevent re-rendering Block Views and Properties#21186
Merged
nielslyngsoe merged 18 commits intomainfrom Mar 9, 2026
Merged
Custom Views: Prevent re-rendering Block Views and Properties#21186nielslyngsoe merged 18 commits intomainfrom
nielslyngsoe merged 18 commits intomainfrom
Conversation
Use stable content key for Lit repeat directive instead of index-based key. Add deferred destruction to extension-slot to preserve extensions controller when elements are moved in the DOM during sorting. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request fixes an issue where custom views in Block List and Block Grid editors were unnecessarily destroyed and recreated during drag-and-drop reordering operations, causing performance issues and potential state loss.
Key Changes:
- Modified repeat directive keys from index-based (
${index}_${contentKey}) to stable identifiers (contentKey) in Block List and Block Grid editors - Added deferred destruction pattern to
umb-extension-slotusingsetTimeout(0)to handle DOM moves gracefully - Ensures extension controllers are preserved during DOM reordering while still being properly cleaned up on permanent removal
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/Umbraco.Web.UI.Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts | Implements deferred destruction pattern with timeout management to prevent extension destruction during DOM moves |
| src/Umbraco.Web.UI.Client/src/packages/block/block-list/property-editors/block-list-editor/property-editor-ui-block-list.element.ts | Changes repeat key from index-based to contentKey-only for stable element identity during reordering |
| src/Umbraco.Web.UI.Client/src/packages/block/block-grid/components/block-grid-entries/block-grid-entries.element.ts | Changes repeat key from index-based to contentKey-only for stable element identity during reordering |
...ent/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts
Outdated
Show resolved
Hide resolved
...ent/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts
Outdated
Show resolved
Hide resolved
...ent/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts
Outdated
Show resolved
Hide resolved
Add defensive improvements to the deferred destruction pattern in umb-extension-slot to address potential edge cases: - Verify controller exists before skipping re-initialization on reconnect - Clear any existing pending timeout before setting a new one - Add unit tests for DOM move, permanent removal, and reconnection scenarios 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
...Client/src/packages/core/extension-registry/components/extension-slot/extension-slot.test.ts
Show resolved
Hide resolved
Update test to verify destruction by checking that re-adding the element after permanent removal creates a new extension instance. Disconnected Lit elements don't re-render, so checking shadowRoot children after removal is not a valid assertion. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
...ent/src/packages/core/extension-registry/components/extension-slot/extension-slot.element.ts
Outdated
Show resolved
Hide resolved
Replace setTimeout(0) with requestAnimationFrame for the deferred destruction pattern in umb-extension-slot. This is more semantically correct for DOM-related operations as it waits for the browser to complete rendering before firing. Suggested by @nielslyngsoe in PR review. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
nielslyngsoe
approved these changes
Mar 9, 2026
Member
nielslyngsoe
left a comment
There was a problem hiding this comment.
Hi @rickbutterfield, I have taken over this PR and turned it into something that gives the expected result. The initial version did cause some trouble, but this turned out to be a good cleanup of the cleanup logic.
nielslyngsoe
added a commit
that referenced
this pull request
Mar 10, 2026
This was referenced Apr 2, 2026
Open
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.
Prerequisites
Description
When blocks are sorted in Block List or Block Grid, elements with custom views (
blockEditorCustomViewextension slot) were being destroyed and recreated, causing unnecessary re-renders and potential state loss.Root cause:
repeatdirective used an index-based key (`${index}_${contentKey}`), causing Lit to see moved items as different itemsumb-extension-slotimmediately destroyed its extensions controller on disconnect, even during DOM movesFix:
repeatkey to use onlycontentKey(stable identifier)umb-extension-slot- usessetTimeout(0)to defer cleanup, which is cancelled if the element is reconnected (as happens during DOM moves)How to test:
🤖 Generated with Claude Code