Subscribe on changes!

Access $slots programmatic in customElement

avatar
Jun 20th 2022

What problem does this feature solve?

I'm trying build custom element in Vue.js and expose as web component. As I exploring what I can do with it. Everything is good but when I'm trying access $slots programmatic, it returns undefined.

It may expensive operation convert that to VNode and returns (not sure that), but returns as DOM Element is okay I think.

What does the proposed API look like?

Let's said we create this component first and name Hello.ce.vue:

<script setup>
import { useSlots } from 'vue';
const slots = useSlots()
console.log("setup: ", slots.default)
</script>

<script>
export default {
  created() {
    console.log('created: ', this.$slots.default)
  },

  mounted() {
    console.log('mounted: ', this.$slots.default)
  },
}
</script>

<template>
  <div>
    <h1>What in slots</h1>
    <slot></slot>
  </div>
</template>

Define the custom element in app.js:

import { defineCustomElement } from 'vue';
import Hello from './Hello.ce.vue';

customElements.define('x-hello', defineCustomElement(Hello));

Than add to HTML:

<x-hello>User Defined Text</x-hello>

We can see for each stage, accessing slots will give undefined.

avatar
Oct 27th 2022

any resolution for now?

avatar
Nov 11th 2022

Native slots work fundamentally different from Vue slots (which are programmatic functions), it's impossible to get the behavior match 100% under the same API, and it will only be confusing if we try to expose them under the same API but with completely different behavior (it's also impossible to reflect this difference in types). This is therefore a wontfix.

You do have a way to access the slot contents - in custom element mode, <slot/> in the template are rendered as native slot elements. You can access them using template refs or this.$el.querySelector('slot'), and then call assignedNodes() on the slot elements.