alexjoverm / v-runtime-template

Vue component for compiling templates on the fly using a v-html like API
MIT License
605 stars 72 forks source link

BE AWARE: NOT MAINTAINED AND FAILING #70

Open Garito opened 4 years ago

Garito commented 4 years ago

This component is not maintained at all and doesn't work properly on some cases

blank-tree commented 4 years ago

@Garito do you have an alternative?

Garito commented 4 years ago

Not that I know of But I'm searching cause I need this feature big time

blank-tree commented 4 years ago

@Garito Same here… it "works" in Vue, but I have duplicated content all over the place with Nuxt…

Garito commented 4 years ago

How I've solved my need: Since I load all the templates at startup, I can do something like this:

<script>
const tmpl = `
<div class="section"
  <template v-if="product">
` + store.state.tmpls.find(t => t.slug === 'productwithitems').code + `
  </template>
  <div class="hero" v-else>
    <div class="hero-body">{{ $t('Loading') }}...</div>
  </div>
</div>
`
export default {
  name:  'Product',
  template: tmpl,
...
}
</script>

I don't use nuxt so I don't know if this will work there

Garito commented 4 years ago

I'm making more test on this issue and I found another way to achieve the same result if you need to pass the template as a component property:

render (cE) {
    const tmplStr = `
<div>
  <template v-if="product">` + this.tmpl.code + `</template>
  <div class="card" v-else>
    <div class="card-content">{{ $t('Loading') }}...</div>
  </div>
</div>
`
    const tmpl = Vue.compile(tmplStr)
    return tmpl.render.call(this, cE)
  }
ThomasKientz commented 4 years ago

Create a javascript component as follow :

// renderer.js

import Vue from 'vue'

export default Vue.component('renderer', {
  functional: true,
  render: function(h, context) {
    if (!context.props.template) return h()
    return h(Vue.compile(context.props.template))
  },
})

Then use it as any other components :

<renderer :template="myTemplate" />

You will need to use the full build to use Vue.compile(), with vue-cli's config file just add :

// vue.config.js

module.exports = {
  runtimeCompiler: true,
  [...]
}

Demo => https://codesandbox.io/s/vue-template-render-3x590

blank-tree commented 4 years ago

@ThomasKientz @Garito Have you found a working solution with SSR and Nuxt.js?

yellow1912 commented 4 years ago

@ThomasKientz interesting, how do you pass through additional props such as templateProps?

edgarsn commented 4 years ago

Indeed this is not maintained for some time now. This lib still works for my existing projects though.

For new projects, I would take a look at this repo: https://github.com/jonwatkins/vue-runtime-template-compiler

It looks like alternative for me.

SikoSoft commented 4 years ago

@edgarsn It does look like this library is indeed more up to date and performs a bit better, but I find it still has issues that arise by its design.

In specific, what I notice is that if you manipulate data from your template (through event handlers in my case), the parent (or expected) component does not actually receive the changes. Instead, a proxy'ed version of the parent template receives changes.

This subtle, yet very significant effect isn't mentioned in the documentation, but renders it less useful for me.

It might work more correctly with objects (I haven't tested), but when I use it for primatives (numbers in this case), the proxy component updates its data, but the parent for whom it received the context from does not update its data.

But it still feels like a step forward from this library, because I can at least hook into vuex to work around this, and not worry about the infinite looping v-runtime-template causes me.

patarapolw commented 4 years ago

Actually I have found a solution that doesn't really need maintenance.

<component :is="{ template, functional: true }">

https://dev.to/patarapolw/vue-runtime-compiler-for-arbitary-markdown-4602

rogerclarkmelbourne commented 4 years ago

@patarapolw

This is an interesting solution, but I'm surprised that the author of this component and also https://github.com/jonwatkins/vue-runtime-template-compiler both wrote the a component to handle this functionality

Can the <component :is method load the contents of the template from an external source e.g. downloaded using axios?

patarapolw commented 4 years ago

It appears that not only { template }, but full blown Vue.extend() can be used for this.

So, { data, template, methods } should easily account for async methods and axios.

rogerclarkmelbourne commented 4 years ago

@patarapolw

OK.

I am trying to migrate a site which where the content pages are currently dynamically loaded from pure HTML templates, into an iPad app, but the problem with loading dynamic content has been a bit of a roadblock, especially as I would now need to have components in these HTML pages.

This component seems to do some of what I need, but as its no longer maintained, things could be a problem.

patarapolw commented 4 years ago

@rogerclarkmelbourne

I edited the one with { template } a bit. Perhaps functional: true should also be declared for better performance; if you don't need this inside the component. (Not sure how much it really helps, though.)

<component :is="{ template, functional: true }" />
calaoa commented 4 years ago

Using <component :is="dynamicComponent"> works great indeed, however has anyone managed to use custom components within such a dynamic component itself, e.g. by adding @Component({components: customComponent}) to the snippet:clap: exposed by @patarapolw? (custom components work fine with v-runtime-template on the other hand).