5

First project with Vue3, trying to determine if a named slot has content supplied on a given page.

In my template I have this:

<div
    :class="{ 'py-20': hasTopContent }"
>
    <slot name="top-content" />
</div>

In my code I have the following:

setup (_, { slots }) {

    const hasTopContent = computed((slots) => {

        console.log(slots.topContent);

        return slots.topContent && slots.topContent().length;
    });

    return {
        hasTopContent
    }
}

The above console.log is returning TypeError: Cannot read properties of undefined (reading 'topContent'). What have I missed? Thanks!

TheRealPapa
  • 4,393
  • 8
  • 71
  • 155
  • 3
    by doing `computed((slots) =>{ .... })` you are creating a function which has `slots` argument (which will be always `undefined`). so the code inside `computed` is using this argument instead of `slots` variable from the parent scope. Just use `computed(() => {....}` instead... – Michal Levý Sep 22 '21 at 13:52

1 Answers1

2

Michal Levý is right

var Main = {
    components: {
      'my-component': MyComponent,
    },
    data() {
      return {
      }
    },
    methods: {
    }
};
const app = Vue.createApp(Main);
app.mount("#app")
<html>
<head>
<style>
  .my-component {
    background-color: #fafafa; 
    padding: 5px 20px 20px 20px;
  }
</style>
</head>
<body>
<div id="app">
  <h3>With top slot</h3>
  <my-component class='my-component'>
      <template v-slot:top>
        <h4>Top Slot</h4>
      </template>
  </my-component>
  <h3>Without top slot</h3>
  <my-component class='my-component'>
  </my-component>
  <hr style='padding: 20px 20px 20px 20px;' />
</div>
<script src="//unpkg.com/vue@next"></script>
<script type="text/x-template" id="my-component">
<div
    :class="{ 'py-20': hasTopContent }">
    <slot name="top" />
    hasTopContent: {{hasTopContent}}
</div>
</script>
<script type="text/javascript">    
    var MyComponent = {     
        template: '#my-component',
        setup(_, { slots }) {
        const hasTopContent = Vue.computed(() => {
          return slots.top && slots.top().length > 0;
        });
      return { hasTopContent }
    }
  }
</script>
</body>
</html>
Tolbxela
  • 4,767
  • 3
  • 21
  • 42