Nikola
Nikola

Reputation: 630

VueJS slot in v-for

I want to make a grid component which accepts as slot additional column cell.

<grid>
  <td slot="additional-column">...</td>
</grid>

In the actual component:

<template>
   <table>
     <div v-for="item in items">
       ...
       <slot name="additional-column"></slot>
     </div>
   </table>
</template>

Unfortunately the slot starts repeating itself and this is something vuejs doesn't like.

Duplicate presence of slot "additional-column" found in the same render tree - this will likely cause render errors.

Does anybody know how can I deal with this issue?

Thanks in advance!

Upvotes: 21

Views: 32413

Answers (2)

trk
trk

Reputation: 2236

This definitely seems to be your issue. You could do it this way too (as described here). See last paragraph before the subheading Destructuring.

Parent:

<grid>
  <td :slot="['additional-column', item].join('-')" v-for="item in items">
  ...
  </td>
</grid>

Child:

<table>
    <div v-for="item in items">
        ...
        <slot :name="['additional-column', item].join('-')"></slot>
    </div>
</table>

PS: I have NOT tried this out. If you have difficulties I could create a fiddle and share.

Upvotes: 19

Andrei Glingeanu
Andrei Glingeanu

Reputation: 652

Make the item a nested component (which you'll be repeating using v-for) and render the additional-column slot in that particular component.

That's the proper way to overcome this issue. The idea is that you need to have one single slot with a particular name per component.

That is, you could do it that way, which is a very rough version of it but nicely outlines the idea:

<!-- Grid Template -->
<template>
  <table>
    <GridItem :item="item" v-for="item in items">
      <!-- Maybe even pass that column conditionally, based on the item data -->
      <div slot="additional-column">
        Content of column
      </div>
    </GridItem>
  </table>
</template>


<!-- GridItem Template -->
<template>
  <div>
    <div>Column 1</div>
    <div>Column 2</div>
    <slot name="additional-column" />
  </div>
</template>

Upvotes: 6

Related Questions