Matanya
Matanya

Reputation: 6346

Multiple root nodes in Alpine.js

Building a data table with the latest Alpine.js (v3.7.0). Ran into a problem when trying to implement child rows (i.e an additional togglable row under the main/parent row).

Simplified version:

<tbody>
<template x-for="row in currentPageData" :key="row.id">
    <tr>
        <td>foo</td>
        <td>bar</td>
        <td>baz</td>
    </tr>
    <tr>
        <td colspan="3">
            Some additional content
        </td>
    </tr>
</template>
</tbody>

While I'm not getting any errors in the console, the second node (tr) is not rendered. I assume that's because Alpine requires a single root element. Is there any way around it, as wrapping with div is invalid HTML and a tbody wrapper breaks the layout?

Upvotes: 4

Views: 1246

Answers (2)

flappix
flappix

Reputation: 2227

Since multiple tbody tags are allowed inside one table you can wrap your multiple tr tags in one tbody tag.

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/cdn.min.js"></script>

<table>
    <template x-for="i in [1,2,3]" :key="i">
        <tbody>
            <tr>
                <td>Test</td>
            </tr>
            <tr>
              <td>Test2</td>
            </tr>
        </tbody>
    </template>
</table>

Upvotes: 2

Matanya
Matanya

Reputation: 6346

Thanks to Alpine templates being rendered server-side I ended up with the following workaround:

When table has child rows I remove the root tbody and wrap each tr pair with a tbody of its own.

EDIT (23-9-22):

As per @NoobnSad's request code in twig:

{% if not options.enableChildRows %}
<tbody>
{% endif %}
<template x-for="row in currentPageData" :key="row.id">
    {% if options.enableChildRows %}
    <tbody>
    {% endif %}
<tr>
    {% if options.enableChildRows %}
        {% include datatable.componentPath('childRowToggler') %}
    {% endif %}
    {% include datatable.componentPath('tableCells') %}
</tr>
{% if options.enableChildRows %}
{% include datatable.componentPath('childRow') with {tableHandle:datatable.handle} %}
</tbody>
{% endif %}
</template>
<template x-if="recordsCount===0">
{% include datatable.componentPath('notFound') %}
</template>
{% if not options.enableChildRows %}
</tbody>
{% endif %}

Upvotes: 3

Related Questions