0
votes

I'm just looking into the Svelte framework for an upcoming project.

I was wondering (as it's a project requirement) whether it's possible to load some HTML string from a server (using the fetch api) and insert this into a Svelte component dynamically.

It seems possible to output HTML strings using {@html my_html_string}. Is there any way to have the tags for actual Svelte elements within the HTML string?

e.g.

<script>
    // import MyCustomElementHere....

    let my_html_string = 'Some text <MyCustomElement/> some more text';
</script>    

<p> {my_html_string} [somehow??] </p>

I was thinking this might be possible by turning a component into a Custom Element (or something), but I haven't managed to make this work (probably as I don't know enough about the framework yet).

Does anyone know if it's actually possible?

3

3 Answers

6
votes

It's not possible to do something like {@html "<MyComponent/>"}. That would require the generated code to include an HTML parser, which would increase bundle size significantly.

As you say though, you could do something very similar by compiling <MyComponent> to a custom element called <my-component> instead, and using that string. We need to finish the docs around that, but basically you need to add some metadata to the component...

<svelte:options tag="my-component"/>

...then pass the customElement: true option to the compiler.

-1
votes

I assume it is not possible to do something like:

<script>
let comp="MyComponent"
</script>

<{comp} />
-1
votes

Here is an idea: you could parse the string to find which custom element needs to be shown and then do something like this:

<script>
    import MyCustomElemen from ...

    let my_html_string = 'Some text <MyCustomElement/> some more text';
    // assume u parsed it
    let element_to_use = MyCustomElement;
    let html1 = 'Some text ';
    let html2 = ' some more text'
    new element_to_use({
      target: document.getElementById("someId"),
      props: {
        // whatever your component needs
      }
    })
</script>    

<div>
  <div
    contenteditable="true"
    bind:innerHTML={html1}
  ></div>
  <div id="someId"></div>
  <div
    contenteditable="true"
    bind:innerHTML={html2}
  ></div>
</div>

I hope the idea is visible and helpful!