ツRotX
ツRotX

Reputation: 33

Using v-for inside component that uses <slot/>

So I'm trying to create a dynamic tab component with Vue 3 and slots. I got the tabs working, I have Nav and NavWrapper components. I need to be able to v-for with Nav component inside of a NavWrapper Component. Example:

<NavWrapper ref="selector">
   <Nav v-for="test in testFor" :key="test.name" :title="test.name" icon="bx-user">
       <Profile ref="profile" />
   </Nav>
</NavWrapper>

The profile is just another component just for testing.

Inside of NavWrapper template. Important parts:

<div class="bottom max-h-full">
   <slot />
</div>

Script:

setup(props, { slots }) {
    const tabTitles = ref(slots.default().map((tab) => tab.props));
    const selectedTitle = ref(tabTitles.value[0].title);

    provide("selectedTitle", selectedTitle);
    provide("tabTitles", tabTitles);
    return {
      selectedTitle,
      tabTitles,
    };
  },

The error is:

Uncaught TypeError: Cannot read properties of null (reading 'title')

I guess I can't get the title of v-for items I tried to put normal ones manually and v-for ones and normal ones work normally but v-for just gives that error.

I console logged tabTitles and that confirms my theory.

0: {title: 'Profile', icon: 'bx-user'}
1: null

I tried to put Nav in template tag but same error.

I guess I need to wait for v-for to finish or something, I tried searching on StackOverflow but didn't find anything related.

Upvotes: 2

Views: 2157

Answers (1)

Michal Lev&#253;
Michal Lev&#253;

Reputation: 37763

It seems that when rendering v-for, Vue 3 template compiler implicitly wraps all generated elements into a Fragment element.

You can check this example - especially the JS tab (generated render function) of App.vue and also console (where I'm logging the content of default() slot)

So your tabs are not at the root of slots.default() but at slots.default()[0].children

Upvotes: 2

Related Questions