2

Problem

I'm trying to generate svelte component dynamically in a .ts file. Thus, I'm not able to use <svelte:component> element as it can only be used inside .svelte files; in the HTML section. Is it possible to create some kind of svelte component renderer helper function?

Looking for solution

I'd need a logic for function of type: (component: SvelteComponent, props: any) => HTMLElement

Context

I figure rendering components like this might go around most (or maybe even every) intended coding patterns by Svelte, yet it would be a clean solution for what I'm trying to do. Specifically - I'm trying to inject content in Full calendar as it's described here.

2 Answers 2

6

The event can return a DOM node array and you can render any component to DOM nodes directly using the client-side component API, so e.g.:

// Svelte 5
import { mount } from 'svelte';
// ...
eventContent() {
  const content = document.createElement('div');
  mount(Component, { target: content, props: ... });

  return { domNodes: [content] }
}
// Svelte 3/4
eventContent() {
  const content = document.createElement('div');
  new Component({ target: content, props: ... });

  return { domNodes: [content] }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Yup, that the gist of it, works perfectly, thank you H.B.! I'll update my question with an answer of expanded logic so it could be used as a helper function ✌️
2

Following up on H.B. answer, the code could be extracted into a helper function with corrent TS typing like so:

import type {ComponentType} from "svelte";

export const componentToDom = (componentClass: ComponentType, props: object): HTMLElement => {
    const target = document.createElement('div')

    new componentClass({target, props})

    return target
}

And then inside Full calendar config:

eventContent: () => ({domNodes: [componentToDom(MySvelteComponent, {})]})

2 Comments

Regarding types, svelte exports ComponentType which gives you the constructor signature, btw.
H.B., Legend 🤝

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.