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

Cannot use variable values as slot names in loop #868

Open
1 task
spacedawwwg opened this issue Sep 15, 2023 · 5 comments · Fixed by #933
Open
1 task

Cannot use variable values as slot names in loop #868

spacedawwwg opened this issue Sep 15, 2023 · 5 comments · Fixed by #933
Assignees
Labels
- P2-to-be-discussed Needs discussion

Comments

@spacedawwwg
Copy link

spacedawwwg commented Sep 15, 2023

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:

image

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.
@spacedawwwg spacedawwwg changed the title Cannot use mapped values as slot names Cannot use variable values as slot names Sep 15, 2023
@spacedawwwg spacedawwwg changed the title Cannot use variable values as slot names Cannot use variable values as slot names in loop Sep 15, 2023
@spacedawwwg
Copy link
Author

spacedawwwg commented Sep 19, 2023

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>

@bluwy
Copy link
Member

bluwy commented Sep 26, 2023

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.

@bluwy bluwy transferred this issue from withastro/astro Sep 26, 2023
@spacedawwwg
Copy link
Author

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>`
  }
)}`

@Princesseuh Princesseuh added the needs triage Issue needs to be triaged label Nov 12, 2023
@MoustaphaDev
Copy link
Member

MoustaphaDev commented Dec 19, 2023

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.

@MoustaphaDev
Copy link
Member

MoustaphaDev commented Feb 6, 2024

Reopening this as we've reverted the fix made in #963, due to unexpected regressions that it caused unfortunately. I'll be reworking this in the near future.

@MoustaphaDev MoustaphaDev reopened this Feb 6, 2024
@github-actions github-actions bot added the needs triage Issue needs to be triaged label Feb 6, 2024
@MoustaphaDev MoustaphaDev removed the needs triage Issue needs to be triaged label Feb 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
- P2-to-be-discussed Needs discussion
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants