0

I am unable to dynamically render table rows as a row using a child component.

Parent:

<template>
        <template if:true={data.results}>
            <table>
                <tr>
                    <th>ID</th>
                </tr>
        <template for:each={data.results} for:item="result">
            <c-child-table-row key={result.id} rowResult={result}></c-child-table-row>
        </template>
    </table>
    </template>
 </template>

Child:

<template>
    <tr key={rowResult.id}>
        <td>
            {rowResult.id}
        </td>
    </tr>   
</template>

The rows rendered are not rendered as a table even though inspecting the DOM shows they have the appropriate classes.

5
  • 1
    Because LWC uses Shadow DOM you need to be a bit explicit with the CSS. Try adding, in the CSS for Child: :host { display: table-row }. If that works (a variant on this theme did for us), I'll convert this to an answer.
    – Phil W
    Commented Jun 28, 2021 at 19:18
  • yep - this is what i had to do in the past - no other way. if you are using aura attributes as well add them to the component level as well.
    – Ronnie
    Commented Jun 28, 2021 at 20:42
  • 1
    also the tr tag can likely be pulled out as the :host is treated as such
    – Ronnie
    Commented Jun 28, 2021 at 20:42
  • @PhilW, I couldn't get it with the :host CSS above, but this was the problem. As stated in the documentation: "CSS styles defined in a parent component don’t leak into a child"
    – S.B.
    Commented Jun 29, 2021 at 13:22
  • We have successfully done this using :host { display: xxx }. TBH, we used table-header-group for what we were doing (the child was a header row). You could try various other display options if table-row isn't working for you. Alternatively, move the <tr> into the parent and have the child simply render a sequence of td elements? Or as Ronnie said, simply remove the <tr> from the child template since the outer-most <template> is what is being treated as a row via the CSS.
    – Phil W
    Commented Jun 29, 2021 at 14:08

1 Answer 1

2

LWC uses Shadow DOM and custom elements. You are wanting to generate a structure like:

<table> <!-- from parent -->
  <tr><td>X</td></tr> <!-- from child -->
...

However, what you actually get is something like:

<table> <!-- from parent -->
  <c-child> <!-- from parent -->
    <tr><td>X</td></tr> <!-- from child -->
  </c-child> <!-- from parent --> 
...

To handle this:

  1. Add CSS to the child of the form: :host { display: table-row }
  2. Remove the tr tag from the child, since the above CSS means that the c-child element is treated like a TR (because this is what is actually included in the DOM in place of the outer-most template element in the child LWC's template).

This will result in markup of the form:

<table> <!-- from parent -->
  <c-child> <!-- from parent -->
    <td>X</td> <!-- from child -->
  </c-child> <!-- from parent --> 
...

with the c-child element being treated as if it were a tr, due to the child's CSS, so effectively:

<table> <!-- from parent -->
  <tr> <!-- "from" child due to CSS -->
    <td>X</td> <!-- from child -->
  </tr> <!-- "from" child due to CSS --> 
...

(I have ignored key values and looping you'll need for iteration)

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .