javascriptvue.jsvuejs2

Vuejs doesn't render components inside HTML table elements


I want to render a custom component that displays a row inside a table.

I have the following code:

// js file
Vue.component('message-row', {
    data: function () {
        return {
            msg: 'Hello'
        }
    },
    template: '<tr><td>{{ msg }}</td></tr>'
});

new Vue({
  el: '#app'
});


// html file
<div id="app">
    <table><message-row></message-row></table>
</div>

The problem is that the row ends up rendered outside the table! Like this:

<div id="app">
    <tr><td>Hello</td></tr>
    <table></table>
</div>

You can check it out in this JSFiddle https://jsfiddle.net/eciii/7v6yrf3x/

I'm not sure if this is a bug or I'm just missing something really obvious here...


Solution

  • See Vue.js's documentation about DOM Template Parsing Caveats (Vue3):

    Some HTML elements, such as <ul>, <ol>, <table> and <select> have restrictions on what elements can appear inside them, and some elements such as <li>, <tr>, and <option> can only appear inside certain other elements.

    This will lead to issues when using components with elements that have such restrictions. For example:

    <table>
      <blog-post-row></blog-post-row>
    </table>
    

    The custom component <blog-post-row> will be hoisted out as invalid content, causing errors in the eventual rendered output. Fortunately, the is special attribute offers a workaround:

    <table>
      <tr is="blog-post-row"></tr>
    </table>
    

    You need to add the component using the is attribute as follows.

    <table><tr is="message-row"></tr></table>
    

    See https://jsfiddle.net/7v6yrf3x/1/.