diff --git a/src/lib/components/portal/portal.test.ts b/src/lib/components/portal/portal.test.ts index 580d07a..9dc518a 100644 --- a/src/lib/components/portal/portal.test.ts +++ b/src/lib/components/portal/portal.test.ts @@ -290,3 +290,46 @@ it('should be possible to force the Portal into a specific element using PortalG `"
B
I am in the portal root
"` ) }) + +it('should cleanup the Portal properly when Svelte would not detach it', async () => { + expect(getPortalRoot()).toBe(null) + + render(svelte` + +
+ + {#if render} +
+ +

Contents 1 ...

+
+
+ {/if} +
+ `) + + let a = document.getElementById('a') + + expect(getPortalRoot()).toBe(null) + + // Let's render the first Portal + await click(a) + + expect(getPortalRoot()).not.toBe(null) + expect(getPortalRoot().childNodes).toHaveLength(1) + + // Let's remove the first portal + await click(a) + + expect(getPortalRoot()).toBe(null) + + // Let's render the first Portal again + await click(a) + + expect(getPortalRoot()).not.toBe(null) + expect(getPortalRoot().childNodes).toHaveLength(1) +}) diff --git a/src/lib/hooks/use-portal.ts b/src/lib/hooks/use-portal.ts index ebc32aa..bbda7e5 100644 --- a/src/lib/hooks/use-portal.ts +++ b/src/lib/hooks/use-portal.ts @@ -11,6 +11,11 @@ export function portal( newTarget.append(element); }, destroy() { + // Need to detach ourselves--we can't rely on Svelte always detaching + // us since we moved in the component tree. + if (target?.contains(element)) { + target.removeChild(element); + } if (target && target.childNodes.length <= 0) { target.parentElement?.removeChild(target); }