Kai021195
Kai021195

Reputation: 833

How to get slots's html content as string in vue3?

I want to pass slot's content into a wrap components which one of it's prop will accept html string and render it, here's the code

Parent.vue

<Ellipsis style="max-width: 240px"
  >Genes that helped people survive during the time of the Black Death are
  more likely to be found in people with autoimmune diseases alive today.
  Does this tell scientists anything about what surviving the COVID-19
  pandemic might mean for the world’s population?
  <template #tooltip>
    <div style="text-align: center">
      <i>Lorem Ipsum</i><br />
      Sed ut perspiciatis unde omnis<br />
      iste natus error sit voluptatem accusantium doloremque
      laudantium,<br />
      totam rem aperiam
    </div>
  </template>
</Ellipsis>

Ellipsis.vue

<template>
  <Tooltip
    ref="tooltipRef"
    :content="tooltipContent"
  >
    <span
      ref="content"
      :class="ellipsisClassRef.valueOf()"
      :style="ellipsisStyleRef"
      @click="handleClickRef"
    >
      <slot></slot>
    </span>
    </Tooltip>
</template>

setup(props, { slots }) {
    onMounted(() => {
      if (slots.default !== undefined) {
        tooltipContent.value = slots.default()[0].children;
      }
      if (slots.tooltip !== undefined) {
        // have to get the html content like below 
        tooltipContent.value = `<div style="color: blue">hello world</div>`;

      }
    });
}

So the main problem is how to convert the slot's content( html content) I got from parent, and turn it into the string and pass it to the wrap content. When I console.log(slots.tooltip), I know I can get the html content like a nested object like following,

0
: 
{__v_isVNode: true, __v_skip: true, type: 'div', props: {…}, key: null, …}
length
: 
1
[[Prototype]]
: 
Array(0)
at
: 
ƒ at()
length
: 
1
name
: 
"at"
arguments
: 
(...)
caller
: 
(...)
[[Prototype]]
: 
ƒ ()
concat
: 
ƒ concat()
constructor
: 
ƒ Array()
copyWithin
: 
ƒ copyWithin(

but there a lot of things to cover if I want to concat them into a string, so I wonder if there's a way to just get the html content as a string or like a helper function to call to get format like <div style="color:blue">Hello world</div>.

Upvotes: 4

Views: 2209

Answers (1)

Tolbxela
Tolbxela

Reputation: 5183

You can use v-html directive to return Raw HTML.

<span v-html="rawHtml"></span>

The other option could be Fallback Content in the slot, if the fallback content is static.

<button type="submit">
  <slot>
    Submit <!-- fallback content -->
  </slot>
</button>

But if the slot content is dynamic, then you should better use the Render Functions

h('div', { style: { color: 'blue' }, innerHTML: 'hello world' })

Check my other answer here for details:

Adding custom HTML element inside template using functions Vue.js


Example

const { createApp, h } = Vue;

const myComponent = {   
  setup(props) {
    return () => h('div', { style: { color: 'blue' }, innerHTML: 'hello world' })
  }
}

const App = {
  components: { 
    myComponent
  }
}

const app = createApp(App)
app.mount('#app')
<div id="app">  
  <my-component></my-component><br/>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>

Upvotes: 1

Related Questions