3

I'm using Svelte, and I want to create a component that will allow me to do something like this:

<CodeDisplay>
    <button class="btn">Button</button>
</CodeDisplay>

CodeDisplay.html should look something like this:

<slot></slot>
<code><slot></slot></code>

Essentially, what I want is a component that will first render the HTML code that I place within the component, and then I want to display the code itself. (I'm building a documentation system.)

Seems to be like you can't use <slot></slot> more than once which makes sense.

How would I accomplish what I'm trying here. I really want to avoid duplicating the HTML code twice in my code for every example in the documentation. I just thought it would be nice to have a component that in general, I can pass some HTML, and then the component will render the HTML and show the code.

EDIT: I just realized I could do something like this:

{{{html}}}
<pre><code>{{html}}</code></pre>

<script>
  export default {
    data() {
      return {
        html: '',
      }
    }
  };
</script>

And display it like this:

<CodeDisplay html='<button class="btn">Button</button>'/>

But I'm getting some errors with this (that happen inconsistently).

Justin
  • 623
  • 1
  • 10
  • 24

1 Answers1

2

Have you seen named <slot>s?

<slot name="slot-one"></slot> // Show rendered HTML
<slot name="slot-two"></slot> // Show HTML as string

When you create your HTML-snippet example with backticks, you can render it in slot-one and display it as a (nicely formatted multi-line) example in slot-two:

let mySnippet = `<div>
                    <div>
                        <span>Hello</span>
                    </div>
                </div`;

I'm not a SvelteJS expert, but you you can test/check here with this example.

Jeffrey Roosendaal
  • 6,872
  • 8
  • 37
  • 55
  • I did read that section in the docs. I don't believe that accomplishes what I'm trying to do. – Justin Mar 21 '18 at 21:31
  • So I saw your edit, and that brings to my latest idea on how I can accomplish what I want. Basically, have a JSON file that stores the HTML markup using template strings with backticks like you said. Then, I can loop through the JSON in my template code and pass in a binding instead of a . This way my CodeDisplay component can have look more like: {{html}}{{html}} – Justin Mar 21 '18 at 21:36
  • Again, I should reiterate that what I would like is to only have to write the HTML once, and the component would then be responsible for rendering the HTML and the HTML code itself. – Justin Mar 21 '18 at 21:39
  • It's always a goo idea to store data in a JSON, and use components to display a block of content (keeps your code clean and readable). I haven't really used SvelteJS myself, I just knew about the name slots, since a lot of Js frameworks got those (or something similar). I can't really help you any further, but I hope I've pointed you in the right direction with the named slots and the backticked HTML. – Jeffrey Roosendaal Mar 21 '18 at 21:43
  • I've edited my question to include an alternative way for me to accomplish what I want. Difference between two curly braces and three. ({{ vs {{{) – Justin Mar 21 '18 at 21:47
  • Would have been nicer to use the slot method though, because putting HTML as a binding doesn't look nice. – Justin Mar 21 '18 at 21:48