[Vuejs]-Vuejs – Data not showing in array – No errors

2👍

I’m not 100% what you’re trying to accomplish, but I think you’ve misunderstood how slots work.

Slots

The <slot> element lets you distribute content into a component. Here is a small example:

Vue.component('child-component', {
  template: '#child-component'
});

new Vue({
  el: '#app',
  data: { message: 'Hello I have been slotted' }
});
  
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>
<div id="app">
  <child-component>
    {{ message }}
  </child-component>
</div>

<template id="child-component">
  <div>
    <p>Above the slot</p>
    <slot></slot>
    <p>Below the slot</p>
  </div>
</template>

Essentially, any html between the component tags gets put into the slot. You can read more about slots in the documentation here.

The Problem

You have tried to slot three moustache components into moustaches, but moustaches doesn’t have a slot.

Also, you have given the moustache components slots, but haven’t slotted anything in.

Solution #1

Add a slot to the moustaches component. Because the moustache components are empty divs, they will not show up on the page. Here is a working code snippet:

Vue.component('moustaches', {
  template: '#moustaches',
  data() {
    return { moustaches: [] };
  },
  created() {
    this.moustaches = this.$children;
  }
});

Vue.component('moustache', {
  template: '<div><slot></slot></div>',

  props: {
    name: { required: true },
    img: { required: true},
    selected: { default: false }
  }

});

new Vue({
  el: '#app'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>

<div id="app">
  <moustaches>
    <moustache name="The Burgundy" img="/img/the-burgundy.jpg"></moustache>
    <moustache name="The Borat" img="/img/the-borat.jpg"></moustache>
    <moustache name="The Santana" img="/img/the-santana.jpg"></moustache>
  </moustaches>
</div>

<template id="moustaches">
  <div>
    <ul class="list-inline">
      <li v-for="moustache in moustaches">
        <p>
          <strong>@{{ moustache.name }}</strong>
        </p>
        <img width="300" height="200" :src="moustache.img">
        <button 
                class="btn btn-primary" 
                :data-type="moustache.name"
                >
          Vote
        </button>
      </li>
    </ul>
    <slot></slot>
  </div>
</template>

I do not recommend this approach, because you are using the slot only to pass data. Slots should be used to pass html, not data. It is a strange way of doing things and you’ll likely run into other bugs.

Solution #2

Instead of using a slot to pass data, you should be passing data via props. By moving the data out of the html, and into the parent component, we can get rid of all slots and the moustache component entirely:

Vue.component('moustaches', {
  template: '#moustaches',
  props: ['moustaches'],
});

new Vue({
    el: '#app',
    data: {
        moustaches: [
        { name: "The Burgundy", img: "/img/the-burgundy.jpg" },
        { name: "The Borat", img: "/img/the-borat.jpg" },
        { name: "The Santana", img: "/img/the-santana.jpg" },
      ]
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.4/vue.js"></script>

<div id="app">
  <moustaches :moustaches="moustaches"></moustaches>
</div>

<template id="moustaches">
  <div>
    <ul class="list-inline">
      <li v-for="moustache in moustaches">
        <p>
          <strong>@{{ moustache.name }}</strong>
        </p>
        <img width="300" height="200" :src="moustache.img">
        <button 
                class="btn btn-primary" 
                :data-type="moustache.name"
                >
          Vote
        </button>
      </li>
    </ul>
  </div>
</template>

0👍

The above poster kindly answered the question much better than I could but TL:DR answer is I was missing <slot></slot> in the Moustaches component.

I just added it below the closing div and it worked.

Leave a comment