Discussion icon indicating copy to clipboard operation
Discussion copied to clipboard

How to change component template dynamically

Open Anshul-Batra opened this issue 9 years ago • 12 comments

Hi,

I want to change Component's template string dynamically. The component is already attached to DOM. Then I change the template at run time. I want that change to get reflect in UI.. Please let me know the way.

Currently i am creating a component using below method

Vue.component('Comp1', {
                'template':'Loading...'
            });

Then when my data loads and i get template str in templatestr variable then again i am doing:

Vue.component('Comp1', {
                'template': templatestr 
            });

I am again creating a new component with the same name but this time with new template string. ideally it should replace the previously attached component with the new one. But it is not working as per the expectation. Please tell me if i am wrong somewhere.

Thanks, Anshul

Anshul-Batra avatar Jun 15 '15 07:06 Anshul-Batra

Use v-if or v-show directives to show/hide things:

<p v-if="loading">Loading...</p>
<template v-if="!loading">
  <!-- loaded data here -->
</template>

azamat-sharapov avatar Jun 15 '15 07:06 azamat-sharapov

i cannot use v-if because more than 50 templates are being loaded dynamically on demand of user.

Anshul-Batra avatar Jun 15 '15 08:06 Anshul-Batra

I think you are approaching this with wrong assumptions. Templates for a component is static, once it's defined you can't change it. You need to express the parts that may be changed inside the template.

It's probably a good use case for the deprecated partial syntax... or, I can make v-html automatically compile its content.

yyx990803 avatar Jun 15 '15 14:06 yyx990803

I have a problem... I am trying to make a 'view source' component. The template is in an external file loaded with jQuery. I use async component syntax to declare it., it's like that:

Vue.component('source-view', function (resolve, reject) {
    loader('/ScriptsLocal/components/SourceView.html').done(tpl => {
        resolve({
            template: tpl,
            data: function () {
                var result = { text: null };
                if (this.selector) {
                    var eHtml = $(this.selector);
                    if (eHtml && eHtml.length)
                        result.text = eHtml.html();
                }
                return result;
            },
            props: {
                selector: {
                    type: String,
                    required: false,
                },
            },
        });
    }).fail(x => reject(x));
})

The problem with that is it always get the HTML after Vue has updated it, I would like to get the early html, showing all the bindings!!! Any idea how I could do that with template in an external file?

Not in my HTML page I use the sourceView component like that:

  <source-view title="Source code: view" selector=".liveExample"></source-view>

superlloyd avatar Oct 18 '15 01:10 superlloyd

@yyx990803 I think that would be nice that v-html compiles its template. Otherwise how are we supposed to manage this kind of behavior ? I have a list that can display 300 types of element. I'm not going to load them all. I'll just load those I need to display the list.

I feel like there is a lack of support on run-time loading component from the server. I always get stuck when it comes to download a template and bootstrap it in my Vue...

Elfayer avatar Dec 06 '16 09:12 Elfayer

I think I found a decent solution to this problem, using render function: https://jsfiddle.net/gm4uf485/2/

new Vue({
  el: '#app',
  data: {
    msg: 'hello',
    template: null
  },
  render: function(createElement) {
    if (!this.template) {
      return createElement('div', 'Loading...');
    } else {
      return this.template();
    }
  },
  mounted() {
    var self = this;
    setTimeout(function() {
    	self.template = Vue.compile('<div><span>{{ msg }}</span></div>').render;
    }, 1000);
  }
})

Elfayer avatar Dec 06 '16 11:12 Elfayer

@Elfayer it doesn't work on vue 2.

have this error message: Uncaught TypeError: _vue2.default.compile is not a function(…)

jeblister avatar Dec 17 '16 17:12 jeblister

@jeblister See the JSFiddle above, it does use Vue2. You might be using the runtime-only version. You need the standalone version to use Vue.compile(). See: https://vuejs.org/v2/guide/installation.html#Standalone-vs-Runtime-only-Build

But here is a more appropriate example (more complexe too): https://jsfiddle.net/Linusborg/47ejdvyy/6/ From the forum: https://forum.vuejs.org/t/vue-compile-what-is-staticrenderfns-render-vs-staticrenderfns/3950/12

Elfayer avatar Dec 18 '16 10:12 Elfayer

@Elfayer Thank you very much !

jeblister avatar Dec 18 '16 12:12 jeblister

@Elfayer @LinusBorg

A problem with the second example (using functional components to render dynamic templates) seems to be strange reactivity. It looks like any state change, even those unrelated to functional components' props, will trigger re-rendering: https://jsfiddle.net/mcgullenz/c7vqwbkm/

Is this to be expected or am I doing something wrong? Thanks.

superharry avatar Aug 16 '17 07:08 superharry

This repo is deprecated, please forum.vuejs.org

LinusBorg avatar Aug 16 '17 09:08 LinusBorg

does this work with server side rendering also?

shivgarg5676 avatar Apr 16 '18 12:04 shivgarg5676