VueJS - Pass slot to child of child component

20,585

Solution 1

Slots are the best approach and you will need to use a scoped slot for the contact-list-item component. I'm not really familiar with pug, so I will use HTML for the example.

In contact-list you would add a slot. Notice in this case that the contact is being passed as a property. This is so we can take advantage of scoped slots.

<div class="table">
  <div class="table-header table-row">  
    <div class="table-col">Contact</div>
    <div class="table-col">Info</div>
  </div>
  <div class="table-body">
    <contact-list-item v-for='contact in contacts'
                       :contact="contact"
                       @click="doSomething"
                       :key="contact.id">
      <slot :contact="contact"></slot>
    </contact-list-item>
  </div>
</div>

Then add a slot to the contact-list-item.

<div class="table-row" @click="emitClickEvent">
  <div class="table-col">{{contact.name}}</div>
  <div class="table-col">{{contact.info}}</div>
  <slot></slot>
</div>

Finally, in your Vue template, use the scoped template.

<div id="app">
  <contact-list :contacts="contacts">
    <template scope="{contact}">
      <div class="table-col">{{contact.id}}</div>
    </template>
  </contact-list>
</div>

Here is a working example. I have no idea what your styles are but notice the id column is now displayed in the contact-list-item.

Solution 2

You can use template for registering slot to the child of child component.

There is also a case when you want to have many named slots.

child.vue

<template>
  <div>
    <h2>I'm a father now</h2>
    <grandchild :babies="babies">
      <template v-for="(baby, id) in babies" :slot="baby.name">
        <slot :name="baby.name"/>
      </template>
    </grandchild>
  </div>
</template>

grandchild.vue

<template>
  <div>
    <p v-for="(baby, id) in babies" :key="id">
      <span v-if="baby.isCry">Owe...owe...</span>
      <slot :name="baby.name">
    </p>
  </div>
</template>

parent.vue

<template>
  <div>
    <h2>Come to grandpa</h2>
    <child :babies="myGrandChilds">
      <button slot="myGrandChilds[2].name">baby cry</button>
    </child>
  </div>
</template>
Share:
20,585

Related videos on Youtube

felipeecst
Author by

felipeecst

Updated on July 09, 2022

Comments

  • felipeecst
    felipeecst almost 2 years

    I have a list and a list_item component that I reuse a lot inside my application. On a simplified form:

    contact_list.vue

    <template lang="pug">
        .table  
          .table-header.table-row
            .table-col Contact
            .table-col Info
    
          .table-body
              contact-list-item(v-for='contact in contacts',
                                :contact='contact',
                                @click='doSomething()')
    
    </template>
    

    contact_list_item.vue

    <template lang="pug">
    .table-row(@click='emitClickEvent')
      .table-col {{ contact.name }}
      .table-col {{ contact.info }}
    </template>
    

    When I use contact_list inside a specific component, I want to be able to send a slot that will add some new columns to the contact_list_item component. This slot will use data of the specific contact that is being rendered inside that contact_list_item component to generate the new columns.

    How could I achieve that? Is using slot the best approach?

    Thanks in advance.

  • aerial
    aerial over 2 years
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review