svelte: (for passing slots through to child components) silently fails

Demo: https://v3.svelte.technology/repl?version=3.0.0-beta.3&gist=853e7d404576d323ca476f7db99ee3d0

It’s reasonable to want to pass a slot through to a child component; the natural way to do this without adding a new DOM node is like this:

<slot name="foo" slot="foo"></slot>

Unfortunately, this doesn’t work, and silently does doesn’t render the slot.

The current workaround is the same as for using components as a slot: create a regular DOM element and use that as the slot:

<div slot="foo">
    <slot name="foo"></slot>
</div>

Vaguely related to #1037/#1713 which are about slot not yet working on components (it currently explicitly fails at compile time with a helpful message, which is a much happier failure mode).

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 6
  • Comments: 15 (8 by maintainers)

Most upvoted comments

In 3.29.0 you can now use <slot slot='...'> to forward slots into a child component, without adding DOM elements.

Would love to see passthrough slots to create superset components, for example Table and TableWithPagination (table slots for TableWithPagination could be passed through to Table).

@endigma I’ve been able to fix this by changing the card component like so:

<script lang="ts">
	let clazz = '';

	export { clazz as class };

	let header: HTMLDivElement;
	let footer: HTMLDivElement;

	$: headerClass = header?.innerHTML ? '' : 'hidden';
	$: footerClass = footer?.innerHTML ? '' : 'hidden';
</script>

<div class="divide-y divide-gray-200 rounded-lg bg-white shadow {clazz}">
	<div class="px-4 py-5 sm:px-6 {headerClass}" bind:this={header}>
		<slot name="header" />
	</div>

	<div class="px-4 py-5 sm:p-6">
		<slot />
	</div>

	<div class="px-4 py-4 sm:px-6 {footerClass}" bind:this={footer}>
		<slot name="footer" />
	</div>
</div>

This technically “works”, but it breaks components that style differently using $$slots.x, as with the most basic approach of <slot slot="one" name="one" />, $$slots.one is true even when the slot is empty. I tried wrapping the slot with an if but the compiler complains:

Element with a slot=‘…’ attribute must be a child of a component or a descendant of a custom element

I don’t see a way around this at the moment, should I make a new issue?

@zeng450026937

Pending @damianpumar’s fix, you might try

<slot slot=“x” name=“x”

edit: so it’s only for un-named slots?

Is it really working? can someone share a working REPL ?