Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<slot slot="…"> (for passing slots through to child components) silently fails #2079

Closed
chris-morgan opened this issue Feb 13, 2019 · 15 comments · Fixed by #4295 or #4556
Closed

<slot slot="…"> (for passing slots through to child components) silently fails #2079

chris-morgan opened this issue Feb 13, 2019 · 15 comments · Fixed by #4295 or #4556
Labels

Comments

@chris-morgan
Copy link
Contributor

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).

@chris-morgan
Copy link
Contributor Author

Turns out my workaround doesn’t work properly either: when you try to fill the passed-through slot, reactivity stops working. Demo updated to demonstrate this.

So it looks as though passing slots through to child components is just completely broken in mostly invisible ways at present.

@Rich-Harris
Copy link
Member

Updated REPL — this now works, though <slot name="foo" slot="foo"> still fails: https://svelte.dev/repl/29649e0f38c142629ef4ef6ed26c4bba?version=3.6.2

Relatedly it would be useful to be able to 'forward' slots including unknown ones (so that the <Message> in this example doesn't need to know about what slots <Greeting> expects)

@briancray
Copy link

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).

@Conduitry
Copy link
Member

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

@galangel
Copy link

galangel commented Oct 5, 2020

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

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

@zeng450026937
Copy link

@Conduitry still not working in ver 3.29.0.
slot attr causing compiler throw validation error: Element with a slot='...' attribute must be a child of a component or a descendant of a custom element

@damianpumar
Copy link
Contributor

@Conduitry still not working in ver 3.29.0.
slot attr causing compiler throw validation error: Element with a slot='...' attribute must be a child of a component or a descendant of a custom element

Yes @zeng450026937 we have an other error related this #5475

Thanks

@arackaf
Copy link
Contributor

arackaf commented Oct 20, 2020

@zeng450026937

Pending @damianpumar's fix, you might try

<slot slot="x" name="x"

@damianpumar
Copy link
Contributor

@zeng450026937

Pending @damianpumar's fix, you might try

<slot slot="x" name="x"

Good morning @arackaf yes, I pushed my fix here #5536 if you want, I can add a test to verify this.

Many thanks!

@PaulMaly
Copy link
Contributor

Using this broke the building process completely and silently, even in REPL: https://svelte.dev/repl/27483a5fc4064f4bb8f3584528d53655?version=3.29.0

Spent half of an hour to find out why the Rollup stopped building an app, no errors occurred and it's the most
bad moment.

@damianpumar
Copy link
Contributor

Using this broke the building process completely and silently, even in REPL: https://svelte.dev/repl/27483a5fc4064f4bb8f3584528d53655?version=3.29.0

Spent half of an hour to find out why the Rollup stopped building an app, no errors occurred and it's the most
bad moment.

This issue was fixed by me 3 days ago here #5536 and it was added to 3.29.1 milestone

Thanks!

@jtlapp
Copy link

jtlapp commented Jun 9, 2022

Should the following work for propagating nested slots back up?

<slot slot="item" name="item" let:label let:item {label} {item} />

I get "cannot find" errors for label and item.

@endigma
Copy link

endigma commented Mar 21, 2023

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?

@hamishjohnson
Copy link

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?

I think I have the same issue as you.

I'm using slots like so:

// Card.svelte
<script lang="ts">
  let clazz = "";

  export { clazz as class };
</script>

<div class={`divide-y divide-gray-200 rounded-lg bg-white shadow ${clazz}`}>
  {#if $$slots.header}
    <div class="px-4 py-5 sm:px-6">
      <slot name="header" />
    </div>
  {/if}
  <div class="px-4 py-5 sm:p-6">
    <slot />
  </div>
  {#if $$slots.footer}
    <div class="px-4 py-4 sm:px-6">
      <slot name="footer" />
    </div>
  {/if}
</div>

Then I have a modal than contains a card like so:

// Modal.svelte
// imagine some other modal html
<Card>
	<slot slot="header" name="header" />

	<slot />

	<slot slot="footer" name="footer" />
</Card>

When I use the Modal without header or footer slots, the Card header/footer areas are still shown.

@hamishjohnson
Copy link

@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>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet