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

TypeError: When using template around template slot #11521

Open
Disservin opened this issue Aug 6, 2024 · 10 comments · May be fixed by #11569
Open

TypeError: When using template around template slot #11521

Disservin opened this issue Aug 6, 2024 · 10 comments · May be fixed by #11569

Comments

@Disservin
Copy link
Contributor

Disservin commented Aug 6, 2024

Vue version

3.4.35

Link to minimal reproduction

https://play.vuejs.org/#eNqFkk1PwzAMhv9KFA4DabRChcvoQIB2gAMgxjESqlp3ZLRJlY8yaep/x0k/VqQybonfx4n92nt6V1VBbYEuaKxTxStDNBhb3TDBy0oqQx5kWV2QXMmSzILQ31zC7JqJOGxTEMaLgbIqEgN4IyT2YHtsk/AchwND59ToVIqcb4KtlgL/3zuY0RRhXoB6qQyXQjO6IF5xWlIU8vvJx4yyMO/j6SekXxPxrd65GKOvCjSoGhgdNJOoDZhWXq2fYYfnQSxlZgukj4hvoGVhXY0tdm9FhmWPOF/to3eRi827Xu0MCN035Qp1ZON5RtFT59NfrR/KjYLI5zHRoIsuZ3KAx4aT8dof8KgLaYhISlgyypFi1GVisJtdi44mx0T3q1+D43vza236ren0PbEa1viRJk3HdQATuBgaH/TicuBOz/5fub6tXiH1Oc+xNf/WbZBBntgCbey4MXni2h/ivTXhgRx7MBFo93zCrI8alBs7ehUFl0F0RZsfhdgklw==

Steps to reproduce

Add another template around the template slot

<template>
  <Comp>
      <template #item>
        <slot />
      </template>
  </Comp>
</template>

so that it looks like this

<template>
  <Comp>
    <template v-if="slots?.default">
      <template #item>
        <slot />
      </template>
    </template>
  </Comp>
</template>
TypeError: Cannot read properties of undefined (reading 'type')

What is expected?

No type error, or an error saying that this syntax isn't support (i'm not sure if this is actually supposed to work?)

What is actually happening?

TypeError: Cannot read properties of undefined (reading 'type')
    at getMemoedVNodeCall (compiler-sfc.esm-browser.js:17146:12)
    at createChildrenCodegenNode (compiler-sfc.esm-browser.js:22946:23)
    at createCodegenNodeForBranch (compiler-sfc.esm-browser.js:22892:7)
    at Array.<anonymous> (compiler-sfc.esm-browser.js:22782:32)
    at traverseNode (compiler-sfc.esm-browser.js:18413:15)
    at traverseChildren (compiler-sfc.esm-browser.js:18365:5)
    at traverseNode (compiler-sfc.esm-browser.js:18407:7)
    at transform (compiler-sfc.esm-browser.js:18302:3)

System Info

No response

Any additional comments?

No response

@Disservin
Copy link
Contributor Author

Workaround just specify the v-if on the slot directly.

    <template #item v-if="slots?.default">
      <slot />
    </template>

@Disservin
Copy link
Contributor Author

Disservin commented Aug 6, 2024

However, there's a drawback that the Component which exposes the item slot still see's a slot being passed, which I wouldn't expect since the v-if condition is false.

Vue Playground

(View the console)

@jh-leong jh-leong added 🔩 p2-edge-case has workaround A workaround has been found to avoid the problem labels Aug 6, 2024
@jh-leong
Copy link
Member

jh-leong commented Aug 6, 2024

However, there's a drawback that the Component which exposes the item slot still see's a slot being passed, which I wouldn't expect since the v-if condition is false.

Vue Playground

(View the console)

You should get the specific slot by the key corresponding to that slot's name, like useSlots().item (Playground).

@Disservin
Copy link
Contributor Author

However, there's a drawback that the Component which exposes the item slot still see's a slot being passed, which I wouldn't expect since the v-if condition is false.
Vue Playground
(View the console)

You should get the specific slot by the key corresponding to that slot's name, like useSlots().item (Playground).

Ah yes, it is indeed empty. I only got confused because the slots object wasn't empty
image

but the specific item slot is empty so all is well

@edison1105
Copy link
Member

I think this is an incorrect use of slot

  • The slot name here is default
 <Comp>
    <template v-if="xxx">
      <template #item>
        <slot />
      </template>
    </template>
  </Comp>
  • The slot name here is item
 <Comp>
    <template v-if="xxx" #item>
      <template>
        <slot />
      </template>
    </template>
  </Comp>

@Disservin
Copy link
Contributor Author

Yeah I wasn't entirely sure if this is a valid use.. has it always been like this in the past ? Dunno how I can go further back in the playground..

@jacekkarczmarczyk
Copy link
Contributor

For the following code:

    <my-component-with-hint-slot>
      <template v-if="true">
        <template #hint>hint</template>
      </template>
    </my-component-with-hint-slot>

in Vue 2 I'm getting "<template v-slot> can only appear at the root level inside the receiving component" error from the compiler, I have also eslint warning 'v-slot' directive must be owned by a custom element, but 'template' is not, so I'm pretty sure it was always like this, maybe just the produced errors were different in different versions of Vue

@Disservin
Copy link
Contributor Author

Disservin commented Aug 8, 2024

Ah I think this "<template v-slot> can only appear at the root level inside the receiving component" would be nice to have. Current core code doesn't have this. I had a look at the source and the code is failing during the transform already before even vSlot.ts is reached (where I think this warning should be emitted from?)

@edison1105
Copy link
Member

edison1105 commented Aug 8, 2024

Ah I think this "<template v-slot> can only appear at the root level inside the receiving component" would be nice to have. Current core code doesn't have this. I had a look at the source and the code is failing during the transform already before even vSlot.ts is reached (where I think this warning should be emitted from?)

I agree with this. We need to emit user-friendly error at compile phase to align with vue2

@edison1105 edison1105 added scope: compiler and removed has workaround A workaround has been found to avoid the problem labels Aug 8, 2024
@Disservin
Copy link
Contributor Author

Yes that'd be nice, after going through the vue2 source there were a couple more warnings which don't exist in that form in vue3 but I haven't checked which of these need to be ported to vue3.

Disservin added a commit to Disservin/core that referenced this issue Aug 15, 2024
Implements the warning from vue2 in vue3.

fixes vuejs#11521
Disservin added a commit to Disservin/core that referenced this issue Aug 15, 2024
Implements the warning from vue2 in vue3.

fixes vuejs#11521
Disservin added a commit to Disservin/core that referenced this issue Aug 15, 2024
Implements the warning from vue2 in vue3.

fixes vuejs#11521
Disservin added a commit to Disservin/core that referenced this issue Aug 15, 2024
Implements the warning from vue2 in vue3.

fixes vuejs#11521
Disservin added a commit to Disservin/core that referenced this issue Aug 15, 2024
Implements the warning from vue2 in vue3.

fixes vuejs#11521
Disservin added a commit to Disservin/core that referenced this issue Aug 16, 2024
Implements the warning from vue2 in vue3.

fixes vuejs#11521
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants