<template>
<table>
<tr repeat.for="customer of customers">
<td>${customer.fullName}</td>
</tr>
</table>
</template>
But obviously, the “correct table code” provided in the documentation examples does not suffice for the issue at hand, which requires multiple table rows per collection item.
The solutions provided by @elitastic and @tristanh seem to be working fine, however. But my Visual Studio 2019 environment does complain about the fact that “element ‘tr’ cannot be nested inside element ‘template’”. However, these issues are raised as warnings instead of errors. So I suspected that it is not valid HTML indeed. A quick glance on the Technical Summary section in the documentation of the tr element on the Mozilla Developer Network confirmed this. So it works, but theoretically it seems to be invalid.
Adding or omitting the containerless attribute does not seem to have any effect here (neither functional nor regarding the warnings in VS2019).
So I am still quite curious about possible alternative solutions that do not involve nesting tr elements in a template element.
The main problem here is IE 11, which does not support the template tag (especially in connection with html tables). For modern browsers the following code is totally fine:
<table>
<template repeat.for="customer of customers">
<tr>
<td>${customer.fullName}</td>
</tr>
</template>
</table>
I solved this in my projects by repeating the tbody tag (where possible):
Yes, using a template element works fine indeed. But it still remains a mystery to me why the tr element officially isn’t supposed to be used as a direct child in anything except a table, a thead, a tbody, or a tfoot element, even in other (evergreen) browsers. I guess that’s the reason why my VS2019 environment is warning about it. I can ignore it, but it remains an annoying issue.
Your solution regarding a repeating tbody element is great. Multiple tbody elements are supported just fine. The DOM also provides a tBodies property on the HTMLTableElement class, which I was not aware of until now. And it seems to have full browser support. So I consider this to be a valid solution (until I run into scenarios where it doesn’t work). Thank you very much.