Home > Blockchain >  How to access slot props from the component used inside the slot?
How to access slot props from the component used inside the slot?

Time:09-17

so everything i can find about scoped slots and passing props dont work for my specific situation:

i have following component order:

Home/List/ListItem

now i desided to replace the ListItem with a slot and because i use the List in a other Component too, but in there i need the ListOptionsItem.

in my home component i did this:

               <list 
                class="mapkeyList"
                :content="displayList"
                :filterbar="true"
                @handleSelection="addSelection"
                @delete="deleteElement"
                @editItem="editItem"
                header="Mapkeys"
                :key="mapkeyListKey"
           >
                <list-item>
                </list-item>
           </list>

in my List component i have this:

<template>
 <div>
      <h2 v-if="header">{{header}}</h2>
      <div  class="listContainer"  v-if="showedContent.length > 0">
           
           <div v-for=" (item, index) in showedContent" :key="index">
                <slot 
                     :item="item"
                     :index="index"
                     :dragable="dragableItems"
                     @auswahl="auswahlHandle"
                     @deleteElement="deleteElement"
                     @editItem="editItem"
                     :dontShowButtons="dontShowButtons"
                     @dragStart="handleOverDragStart"
                     :dragItem="dragItem"
                     @position="$emit('emitPosition',item)"
                     :deaktivierbar="deaktivierbar"
                >
                </slot >
           </div>

finaly the listItem and the listOptionsItem need to access this props in the slot:

listItem:

<template>
 <div class= "flexSpaceBetween" @click="$emit('auswahl',item)">
      <div class="textFett">
           {{item[0]}}
      </div>
      <div>
           {{item[1]}}
      </div>
 </div>

i dont want to write all the neccessarry code in the home component because the listOptionsItem does need more informations and more space to write code.

my goal was it to define in the Home component that i want the list to use the listItem component and in the Options component the list should use the listItemOptions component. in the future there could be added new listItem versions.

CodePudding user response:

Any component used inside scoped slot has no implicit access to the slot props. To make them available inside the component, you must pass it down to that component as props explicitly...

<list 
  class="mapkeyList"
  :content="displayList"
  :key="mapkeyListKey">
  <template v-slot:default="{ item }">
    <list-item :item="item">
    </list-item>
  </template>
</list>

If you have a lot of props/events you want to pass along, the ability of both v-bind and v-on to take an object as an argument is very useful because you can pass all the data and event handlers at the same time:

// List component
<template>
<div>
  <h2 v-if="header">{{header}}</h2>
  <div  class="listContainer"  v-if="showedContent.length > 0">
        
    <div v-for=" (item, index) in showedContent" :key="index">
       <slot :props="slotProps" :on="slotEventsHandlers"
       </slot >
    </div>
  </div>
</div>
</template>

<script>
export default {
  computed: {
    slotProps() {
      return {
        item: this.item,
        dragable: this.dragableItems
      }
    },
    slotEventsHandlers() {
      return {
        deleteElement: this.deleteElement,
        dragStart: this.handleOverDragStart
      }
    }
  }
}
</script>

And use it in parent:

<list 
  class="mapkeyList"
  :content="displayList"
  :key="mapkeyListKey">
  <template v-slot:default="{ props, on }">
    <list-item v-bind="props" v-on="on">
    </list-item>
  </template>
</list>
  • Related