13

I'm trying to solve this for Nuxt

Codesandbox of a WIP not working: https://codesandbox.io/s/zw26v3940m

OK, so I have WordPress as a CMS, and it's outputting a bunch of HTML. A sample of the HTML looks like this:

'<h2>A heading tag</h2>
<site-banner image="{}" id="123">Slot text here</site-banner>
<p>some text</p>'

Notice that it contains a Vue component <site-banner> that has some props on it (the image prop is a JSON object I left out for brevity). That component is registered globally.

I have a component that we wrote, called <wp-content> that works great in Vue, but doesn't work in Nuxt. Note the two render functions, one is for Vue the other is for Nuxt (obviously this is for examples sake, I wouldn't use both).

export default {
    props: {
        html: {
            type: String,
            default: ""
        }
    },
    render(h, context) {
        // Worked great in Vue
        return h({ template: this.html })
    }      
    render(createElement, context) {
        // Kind of works in Nuxt, but doesn't render Vue components at all
        return createElement("div", { domProps: { innerHTML: this.html } })
    } 
}

So the last render function works in Nuxt except it won't actually render the Vue components in this.html, it just puts them on the page as HTML.

So how do I do this in Nuxt? I want to take a string of HTML from the server, and render it on the page, and turn any registered Vue components into proper full-blown Vue components. Basically a little "VueifyThis(html)" factory.

5
  • One idea I had was trying to turn the HTML "string" into just a JSX template (by removing the " from the string basically). But I'm not sure that's possible, I couldn't figure it out. Commented May 6, 2019 at 23:47
  • That exact function that works in Vue, doesn't it work in nuxt? Commented May 9, 2019 at 5:39
  • @acdcjunior no it doesn't in Nuxt 2.6.3 Commented May 9, 2019 at 21:07
  • Did you add the nuxt.render to your app variables? Commented May 14, 2019 at 13:29
  • @jalil no I did not, what is that and how? Commented May 14, 2019 at 15:41

5 Answers 5

7

This was what worked and was the cleanest, thanks to Jonas Galvez from the Nuxt team via oTechie.

export default {
  props: {
    html: {
      type: String,
      default: ""
    }
  },
  render(h) {
    return h({
      template: `<div>${this.html}</div>`
    });
  }
};

Then in your nuxt.config.js file:

    build: {
        extend(config, ctx) {
            // Include the compiler version of Vue so that <component-name> works
            config.resolve.alias["vue$"] = "vue/dist/vue.esm.js"
        }
    }
Sign up to request clarification or add additional context in comments.

Comments

6

And if you use the v-html directive to render the html?

like:

<div v-html="html"></div>

I think it will do the job.

2 Comments

No, that won't unpack the Vue components unfortunately.
And if you use this one? alligator.io/vuejs/v-runtime-template
5

This is how I did it with Nuxt 3 :

<script setup lang="ts">
import { h } from 'vue';

const props = defineProps<{
  class: string;
  HTML: string
}>();
const VNode = () => h('div', { class: props.class, innerHTML: props.HTML })
</script>
<template>
  <VNode />
</template>

There was not need to update nuxt.config.ts.
Hopefully it will help some of you.

1 Comment

Hm need to help with this, this is my no TS version ``` <template> <v-node /> </template> <script setup> import { h } from '@nuxtjs/composition-api' const VNode = () => h('div', { class: 'test-class', innerHTML: '<div>html test</div>' }) </script> ``` It gives me this error VNode is not defined, but it's definitely defined! Im using Nuxt v2 with @nuxtjs/composition-api
4

Here's a solution on codesandbox: https://codesandbox.io/s/wpcontent-j43sp

The main point is to wrap the dynamic component in a <div> (so an HTML tag) in the dynamicComponent() template, as it can only have one root element, and as it comes from Wordpress the source string itself can have any number of top level elements.

And the WpContent component had to be imported.

2 Comments

thanks for this example for me didn't work with 'vue-feather-icons' did you have any idea why?
What is exactly you were trying to do? Do you have your code online?
0

I made some changes to your codesandbox. seems work now https://codesandbox.io/s/q9wl8ry6q9

Things I changed that didn't work:

  1. template can only has one single root element in current version of Vue
  2. v-bind only accept variables but you pass in a string.

Comments

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.