When Vue <slot/> in a component is not an option, but you rather get all the data from Ajax request and render HTML inside a Vue Component. Which you might use v-html directive but you found out that raw HTML that contains Vue Components will not render as you expect. While you inspect html you see just the tag name and that’s it, as if nothing has compiled.

To solve this; Vue.compile to the rescue!

Modal

Example below is the Twitter Bootstrap static modal.

<div class="modal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Modal title</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body">
        <p>Modal body text goes here.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary">Save changes</button>
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>
Twitter Bootstrap 4: Modal

Before we make the VueModal.vue component, we make extra component HtmlCompiler.vue

Vue Component HtmlCompiler

Option 1: HtmlCompiler as global component

const div = document.createElement('div')

Vue.component('htmlCompiler', {
  name: 'HtmlCompiler',
  props: ['code'],
  render(h) { 
    div.innerHTML = this.code
    return h(Vue.compile(div.outerHTML))
  }
})
Global Vue: main.js
This will definitely work, but I don’t think it’s a good idea because every function call will create a DIV-element in the Virtual Dom, just because you’re using these functions innerHTML and outerHTML.
Improved the code

Option 2: HtmlCompiler as a component to import later

<script>
const div = document.createElement('div')
export default {
    name: 'HtmlCompiler',
    props: ['code'],
    render(h) { 
        div.innerHTML = this.code
        return h(Vue.compile(div.outerHTML))
    }
}
</script>
Vue Component: components/HtmlCompiler.vue

The Static Modal as Vue Component

Code below will show you HtmlCompiler as the imported version and not as a global Vue Component.

<template>
<div class="modal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" v-text="title">Modal title</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <html-compiler 
        class="modal-body"
        :code="body"></html-compiler>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary">Save changes</button>
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>
</template>

<script>
import HtmlCompiler from './components/HtmlCompiler.vue'
export default {
    name: 'VueModal',
    components: {
        HtmlCompiler
    }
    props: ['title', 'body']
}    
</script>
Vue Component: components/VueModal.vue
I recommend to use HtmlCompiler as global component, I mean all required components that might render in this Modal. This method is fine, if you care about Treeshaking

Refactored Version

Small library

import Vue from 'Vue'

const div = document.createElement('div')
const vueCompile = html => {
  div.innerHTML = html
  return Vue.compile(div.outerHTML)
}

export default vueCompile
Javascript library: lib/vueCompile.js

Vue Component VueModal

<template>
<div class="modal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" v-text="title">Modal title</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body" v-html="compiledBody">
        <p>Modal body text goes here.</p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary">Save changes</button>
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>
</template>

<script>
import vueCompile from './lib/vueCompile'
Vue.component('vueModal', {
  name: 'VueModal',
  props: ['title', 'body'],
  computed: {
    compiledBody () {
      return vueCompile(this.body)
    }
  }
})
</script>
Version 2 Theoretical: components/VueModal.vue

(Work in Progress)