Cannot use variable values as slot names in loop
Astro Info
Astro v3.0.10
Node v20.5.1
System Linux (x64)
Package Manager npm
Output static
Adapter none
Integrations @astrojs/vue
If this issue only occurs in one browser, which browser is a problem?
No response
Describe the Bug
I have tried to use variable values as slot names but it isn't working (see below).
NOTE: I've simplified my use case here for code example only - I do have a valid use case for sending HTML to slots from outside the Example component (tables with HTML content)
This is a simple Vue component using named slots based on values in the props.
<script lang="ts" setup>
export interface Props {
items: {
id: string;
}[];
}
defineProps<Props>();
</script>
<template>
<template v-for="item of items">
<div
v-if="$slots && $slots[item.id]"
>
<slot :name="item.id" />
</div>
</template>
</template>
This is an example of me using the above vue component within an astro file to try populate slots with a mapped value.
---
const items = [
{ id: "1"},
{ id: "2"},
{ id: "abc"}
];
---
<Example items={items}>
{items.map(({ id }) => <p slot={id}>{id}</p>)}
</Example>
Unfortunately I'm being hit with:
I have logged the id and it it is defined... just not when used as the slot name
What's the expected result?
I'd expect astro to use the value to populate the named slot in the child component. with the output:
<div>
<p>1</p>
</div>
<div>
<p>2</p>
</div>
<div>
<p>abc</p>
</div>
Link to Minimal Reproducible Example
https://stackblitz.com/edit/github-vqaya3
Participation
- [ ] I am willing to submit a pull request for this issue.
So I've also tried below...
this no longer errors as currentIndex is set in the code fence.
The console.log(currentIndex) within the loop logs the correct index but the value used by the slot attribute is always 0 (its as if slot completely ignores all loop values)
---
const items = [
{ id: "1"},
{ id: "2"},
{ id: "abc"}
];
let currentIndex = 0;
---
<Example items={items}>
{items.map(({ id }, index) => {
currentIndex = index;
console.log(currentIndex);
return (<p slot={items[currentIndex].id}>{id}</p>)
})}
</Example>
If you paste the original example in https://live-astro-compiler.vercel.app, you can see it's generated as (formatted for readability):
const items = [{ id: '1' }, { id: '2' }, { id: 'abc' }]
return $$render`${$$renderComponent(
$$result,
'Example',
Example,
{ items: items },
{
[id]: () =>
$$render`${items.map(
({ id }) => $$render`${$$maybeRenderHead($$result)}<p>${id}</p>`
)}`
}
)}`
The 5th parameter is the slots object. Looks like it's not generating the slots right. I'm not sure if it's possible to fix this in the compiler, but I'll move it there at the mean time as it's a compiler issue.
If you paste the original example in https://live-astro-compiler.vercel.app, you can see it's generated as (formatted for readability):
const items = [{ id: '1' }, { id: '2' }, { id: 'abc' }] return $$render`${$$renderComponent( $$result, 'Example', Example, { items: items }, { [id]: () => $$render`${items.map( ({ id }) => $$render`${$$maybeRenderHead($$result)}<p>${id}</p>` )}` } )}`The 5th parameter is the slots object. Looks like it's not generating the slots right. I'm not sure if it's possible to fix this in the compiler, but I'll move it there at the mean time as it's a compiler issue.
yeah, so it feels like while processing the map in the compiler, if it detects slot attributes break up the map into something like:
const items = [{ id: '1' }, { id: '2' }, { id: 'abc' }]
return $$render`${$$renderComponent(
$$result,
'Example',
Example,
{ items: items },
{
['1']: () => $$render`${$$maybeRenderHead($$result)}<p>1</p>`,
['2']: () => $$render`${$$maybeRenderHead($$result)}<p>2</p>`,
['abc']: () => $$render`${$$maybeRenderHead($$result)}<p>abc</p>`
}
)}`
I'm not sure how we could fix this. In this case, the key of the slot render function is derived from a value defined inside the scope of the map function, and the compiler can't really tap into the items array and generate render functions of for each value like in your last comment.
Reopening this as we've reverted the fix made in https://github.com/withastro/compiler/pull/963, due to unexpected regressions that it caused unfortunately. I'll be reworking this in the near future.
Any movement on this @MoustaphaDev ?
Nope @spacedawwwg, I didn't get to contribute to Astro in the last few months.
I don't recall the details, but my conclusions after further investigating this for a few days at the time was that it's not possible, but I may revisit this when I get back on board 😄
LGTM
LGTM
I don't think there is any WIP. They had to revert the original work caused regressions.