Search code examples
htmlvue-componentvuejs3vue-composition-api

Tablerow with Vue3 Composition API without Vue.cli not working


My problem is similar to this question: Vue.js table component not working.

The difference is that I use Vue3, with the Composition API and without Vue.cli as follows:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <table>
            <my-tr v-for="(char, i) in chars" :key="i" :char="char" />
        </table>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@3.2"></script>
    <script>
        const myTr = Vue.defineComponent({
            props: ['char'],
            template: '<tr><td>{{char}}</td></tr>'
        });
        Vue.createApp({
            setup() {
                return {
                    chars: Vue.ref(['a', 'b', 'c'])
                };
            }
        }).component('my-tr', myTr).mount('#app');
    </script>
</body>
</html>

The table is not rendered correctly - without causing an error on the console:

<div id="app" data-v-app="">
    <tr>
        <td>a</td>
    </tr>
    <tr>
        <td>b</td>
    </tr>
    <tr>
        <td>c</td>
    </tr>
    <table></table>
</div>

Replacing <table> with <div> fixed it - but replacing the table is not an option for me.

What am I doing wrong?


Solution

  • You are running into a restriction of HTML, where <table> allows only for specific tags as children (tr, thead, tbody, tfoot). This applies to your custom <my-tr> tag. The documentation recommends to use :is as a workaround:

    <tr is="vue:my-tr" v-for="(char, i) in chars" :key="i" :char="char"></tr>
    

    const myTr = Vue.defineComponent({
      props: ['char'],
      template: '<tr><td>{{char}}</td></tr>'
    });
    
    Vue.createApp({
      setup() {
        return {
          chars: Vue.ref(['a', 'b', 'c'])
        };
      }
    }).component('my-tr', myTr).mount('#app');
    table{
      border: 1px solid grey;
    }
    <div id="app">
      <table>
        <tr is="vue:my-tr" v-for="(char, i) in chars" :key="i" :char="char"></tr>
      </table>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue@3.2"></script>