Walt Stoneburner's Ramblings

Currating Chaos

VueJS Hoisting HTML Elements

When using a VueJS template and trying to inject a component inside of a table, such as a tr, the rendered component is hoisted outside of the parent element.

This problem has bitten me repeatedly, again and again.

You write this:

<table>
    <my-component v-for=...>
</table>

And it renders like this:

<tr>...<tr>
<table>
</table>

In a nutshell, there are DOM Parsing Caveats and elements like table have restrictions on what elements can appear inside them. (FYI: ul, ol, select have this issue as well).

The solution is to use VueJS's is attribute:

<table>
  <tr is="my-component" v-for=...>
</table>

This causes the template parsing to be happy, as table (or even a nested tbody) will be getting a "true" tr element, but its content will be rendered by the named component.


UPDATE: In VueJS 3 the v-is tag now evaluates as a Javascript expression! This means you need to pass it a string, as in <tr v-is="'my-component'">. See workarounds.