Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue Component - Rendering in wrong location

I am seeing strange behavior between a vue component and inline template.

Example #1: Inline Template

This is working as expected. The vue component is unchanged as per example #2 below, the only difference is i've copied the template content into the tag as an inline template.

See: https://jsfiddle.net/pobffmnv/

<div class="panel panel-primary">
    <div class="panel-heading">Current Clients</div>
    <table class="table table-hover">
        <thead>
            <tr>
                <th>Client Name</th>
                <th style="text-align: center;">No. Projects</th>
                <th style="text-align: center;">Time (7 days)</th>
                <th style="text-align: center;">Edit</th>
            </tr>
        </thead>
        <tbody>
            <clientlistitem inline-template>
                <tr>
                    <td>Test</td>
                    <td style="text-align: center;">0</td>
                    <td style="text-align: center;">0</td>
                    <td style="text-align: center;">
                        <div class="btn-group btn-group-xs" role="group">
                            <button type="button" class="btn small btn-primary">Edit</button>
                        </div>
                    </td>
                </tr>
            </clientlistitem>
        </tbody>
    </table>
</div>

This correctly shows the following: Correct

Example #2: Not inline

The following is my Vue template. Below is the change to the code to remove the inline template.

See: https://jsfiddle.net/Ld47hoy2/

<template>
    <tr>
        <td>Test</td>
        <td style="text-align: center;">0</td>
        <td style="text-align: center;">0</td>
        <td style="text-align: center;">
            <div class="btn-group btn-group-xs" role="group">
                <button type="button" class="btn small btn-primary">
                    Edit
                </button>
            </div>
        </td>
    </tr>
</template>
<script>
    export default {

    }
</script>

Updated page code:

<div class="panel panel-primary">
    <div class="panel-heading">Current Clients</div>
    <table class="table table-hover">
        <thead>
            <tr>
                <th>Client Name</th>
                <th style="text-align: center;">No. Projects</th>
                <th style="text-align: center;">Time (7 days)</th>
                <th style="text-align: center;">Edit</th>
            </tr>
        </thead>
        <tbody>
            <clientlistitem></clientlistitem>
        </tbody>
    </table>
</div>

However, with the above, the following is displayed: Incorrect

Looking at the source code of the output of the page, it appears to have put the rendered code BEFORE my table...? I am expecting this to be between the <tbody></tbody> tags..

Strange output

Any reason why Vue would output the code to that location instead of the one expected?

like image 837
R. Anderson Avatar asked Sep 22 '17 23:09

R. Anderson


1 Answers

The issue here is that with in DOM templates the templates are first rendered by the browser and HTML tables only allow certain kinds of elements inside. That being the case, the component clientlistitem is first rendered outside the table, then Vue compiles the template which results in the component in the wrong place.

To fix that, use the is special attribute.

<tbody>
  <tr is="clientlistitem"></tr>
</tbody>

The browser will accept this and render the tr in the correct place, but Vue will interpret it as your component.

Here is your fiddle updated.

like image 119
Bert Avatar answered Nov 04 '22 11:11

Bert