[Vuejs]-Slots are missing in custom defineCustomElement implementation

-1👍

So you have something like this in your main.ts file

defineCustomElement({
    styles: component.styles,
    props: component.props,
    setup(props, { slots }) {
        const app = createApp();
        plugins.forEach(plugin => {
            app.use(plugin);
        });
        const inst = getCurrentInstance();
        Object.assign(inst.appContext, app._context);
        Object.assign(inst.provides, app._context.provides);
        return () =>
            h(component, {
                ...props,
                ...slots
            });
    }
});

And if you inspect that slots variable it’s always empty, even when the custom element has something like

<my-component><div>hmmm...</div></my-component>

It appears to be a bug, an alternative way to making this work is to move the setup code in main.ts into your main App.vue setup and using that for your custom element. So App.vue setup would have something like:

// Plugin initialization and the list can probably be exported from main.ts, putting this here for simplicity
import router from './router';
const plugins = [plugins];

const app = createApp();
plugins.forEach(plugin => {
    app.use(plugin);
});
const inst = getCurrentInstance();
Object.assign(inst.appContext, app._context);
Object.assign(inst.provides, app._context.provides);

Then main.ts would be reduced to

const styles: string[] = [];
const modules = import.meta.glob('./**/*.vue');

for (const path in modules) {
    const mod = await modules[path]();
    styles.push(mod.default.styles);
}

App.styles = [styles.flat().join('')];

customElements.define('swim-app', defineCustomElement(App));

Any slots defined in the App component should now work. You can ignore the styles stuff above, that just fixes another bug where child styles aren’t included in the shadow dom styles tag.

Leave a comment