Vue: feature request: dynamically append/remove DOM elements in template

Created on 2 Dec 2016  Â·  8Comments  Â·  Source: vuejs/vue

As far as I understand, currently, once a vm instance has been created, compiled and mounted, the structure of its template is unchangeable -- we can only switch some DOM elements on/off via existing directives like v-show, v-if and v-for (which are already written in the template), but there is no way to dynamically append brand-new elements/child components (which are not written in template in advance) into the template (or into the DOM).

If I am right -- sometimes we do need to dynamically twist the template itself, because the way we twist it is determined by user's random input and cannot be foreseen.

Or there already is a way to achieve this?

Most helpful comment

The idea here is, do you know ahead of time what possible types of content there are? If yes, then everything should be expressed in your templates or render functions, because that keeps your component's render output declarative and predictable. You don't have to follow through chains of imperative code to figure out why something is happening.

If you don't know the content, then you can use v-html with something like:

userContent: ['<div>hi</div>', '<div>bye</div>']
md5-df3966980adf56036c1e88ee31f1125f


^ Be careful about XSS though.

All 8 comments

What specifically cannot be expressed by the built-in constructs? Worst case, you can really express anything with a render function...

If you need static content depending on the user input, then v-html is the way.
If you need dynamic content (e.g. with event bindings), then check out render functions.

There's also <component :is="someComponent">, where someComponent can be either a string name of the component, or the component itself. IIRC, with enough care you can generate components for it dynamically, but I'd advise to explore the simpler options first.

Closing since I don't think the feature request will be fulfilled, as I believe render functions will be sufficient for arbitrarily complex use cases. Feel free to continue the discussion though.

I am not sure if I understand render function right -- can a render function generate new DOM elements or drop elements from DOM in an async way?

For example, consider a vue instance is already rendered and mounted, with an input element and a OK button in it. The user inputs a number n, and then click the OK button, and after n seconds, a new div element will be appended after the OK button, with the number n shown in it.

Then the use can input another n and click OK, waiting for another n seconds to see another div appended... This can be repeated as many times.

In the pre-vue time, we can easily do this via setTimeout and DOM APIs. How to achieve this by :is or render?

(edit)

I know this can be done by pushing the new numbers into an array and using v-for in template -- but what if the new elements to be appended are not in the same structure and therefore cannot be expressed by v-for?

hmmm, we might be able to define all the possible structures of the new elements as many components, and then combine :is and v-for to do this.

The idea here is, do you know ahead of time what possible types of content there are? If yes, then everything should be expressed in your templates or render functions, because that keeps your component's render output declarative and predictable. You don't have to follow through chains of imperative code to figure out why something is happening.

If you don't know the content, then you can use v-html with something like:

userContent: ['<div>hi</div>', '<div>bye</div>']
md5-df3966980adf56036c1e88ee31f1125f


^ Be careful about XSS though.

Also, if you imperatively append to an empty element rendered by Vue, it won't throw away what you appended on re-renders... so technically you can do what you wanted, just not recommended.

got it. many thanks @yyx990803 @simplesmiler !

Heyup, I want to be able to do this Codepen Popup Test I've asked this of React Developers in Stack Overflow and rather than giving me some sort of direction to go in, they just say, "Noo, you can't think like jQuery anymore", Well let me tell you, I'm thinking like Javascript and I want to be able to put any element anywhere on the page I want. There is a nicer version of that script on my site Code is on my Github account

So does this v-html look like it shows promise..?

Thank you in advance Vue type people :-)

Was this page helpful?
0 / 5 - 0 ratings