#Conditionally rendering in Astro component based on slot content

7 messages · Page 1 of 1 (latest)

woven turret
#

Is it possible to conditionally render different elements inside an Astro component depending on the content passed in to <slot/>?
I want to have an element that is removed from the component if no content is passed in

winter sphinxBOT
#

Hi @woven turret. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Yes, it is possible to conditionally render elements in an Astro component based on the content passed into a <slot/>. You can use the Astro.slots.has() function to check if content for a specific slot exists. This can be useful when you want to wrap slot contents, but only want to render the wrapper elements when the slot is being used.

Here is an example from the Astro documentation (https://docs.astro.build/en/reference/api-reference#astroslots):

---
---
<slot />
{Astro.slots.has('more') && ( <aside> <h2>More</h2> <slot name="more" /> </aside>)}

In this example, the <aside> element will only be rendered if there is content for the 'more' slot.

However, it's important to note that there are some limitations to this approach. As mentioned in a Github issue (https://github.com/withastro/astro/issues/3884), whether a slot will be fulfilled is not known until it is rendered. The Astro.slots.has() API only says that there is a child that the compiler discovered that might render.

If you want to conditionally render a component based on whether it has any content, you might need to provide two usages of your component based on whether the content is truthy:

{slotContent ? (
  <Component>
    <Fragment>
      <slot />
    </Fragment>
  </Component>
) : (
  <Component />
)}

In this example, if slotContent is truthy, the component with the slot is rendered. If slotContent is falsy, the component without the slot is rendered.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@woven turret kapa.ai is still learning and improving, please let us know how it did by reacting below

woven turret
#

@winter sphinx is it possible to detect if there is any content in the default slot?

winter sphinxBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Yes, it is possible to detect if there is any content in the default slot using the Astro.slots.has() function. You can check if the default slot has content by passing the string 'default' as an argument to the function.

Here is an example:

---
const hasContent = Astro.slots.has("default");
---
<div class="card">
  {hasContent && <div class="card-content"><slot/></div>}
</div>

In this example, the card-content div will only be rendered if there is content for the default slot.

However, it's important to note that there are some limitations to this approach. As mentioned in a Github issue (https://github.com/withastro/astro/issues/9654), Astro.slots.has("default") might still return true even when the default <slot> has no content in it. This is because Astro.slots.has relies on static analysis rather than runtime values. In this case, Astro knows that default could have a value, so it returns true for Astro.slots.has.

A potential workaround for this issue is to assign a name to the slot. Another workaround mentioned in the same Github issue is to use Astro.slots.render to check if the string is empty or not, but this could potentially increase build times.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: