hybridsjs / hybrids

Extraordinary JavaScript UI framework with unique declarative and functional architecture
https://hybrids.js.org
MIT License
3.03k stars 85 forks source link

Dynamic columns not showing when render a html table #244

Closed woyodb closed 5 months ago

woyodb commented 5 months ago

Hi, I am trying to render a table with some dynamic columns, but encountered a problem: The columns does not render at all.

If I remove the column, the dynamic columns will rendered.

...
    tag:'my-el',
    items: {
           get: (host, last_v = [1,2] ) => last_v,
           set:(host, v, last_v) => v,
    },
...
        <thead>
            <tr>
                         <th>AAA</th>    
                ${items && items.map(it=>html`
                 <th>BBB_${it}</th>
                `)}
            </tr>
        </thead>
        ...

The full demo code is here :

import { html, define } from "hybrids";
export default define({
    tag:'my-el',
    items: {
        get: (host, last_v = [1,2] ) => last_v,
        set:(host, v, last_v) => v,
    },
    render: ({items}) => html`
     <table>
        <thead>
            <tr>
              <th>AAA</th>
                    ${items && items.map(it=>html`
                       <th>BBB_${it}</th>
                    `)}
            </tr>
        </thead>
        <tbody>
                <tr>
                ${html`<td>aaa</td>`}
                    ${items.map(it=>html`
                        <td>bbb_${it}</td>
                    `)}
                </tr>
        </tbody>
     </table>
    `.css``
});

Please help me to get through this . Thanks...

My local verion is v8.2.11

smalluban commented 5 months ago

Please look at this section of the documentation: https://hybrids.js.org/#/component-model/templates?id=limitations

This is a platform (basically some of the browser implementation) limitation, that template engine cannot use it's internal way to mark place where the expression should be putted.

In short, you cannot use:

html`<th>BBB_${it}</th>`

You must write:

html`<th>${`BBB_${it}`}</th>`

The difference here is that whole content of the <th> element is an expression, which contains a string value.

BTW, to avoid making a set/get property with default value of an array (in v9 it will be possible by value option) you may try this pattern:

  items: undefined,
  render: ({ items = [1,2] }) => html`...`,
woyodb commented 5 months ago

I have changed my codes as you mentioned limitation section, but, still have a confused problem:

     <table>
        <thead>
            <tr>
                  ${html`<th>AAA</th>`}
                    ${items && items.map(it=>html`
                       <th>${`BBB_${it}`}</th>
                    `)}
            </tr>
        </thead>
        <tbody>
            <tr>
            ${html`<td>aaa</td>`}
            ${items.map(it=>html`
            <td>${`bbb_${it}`}</td>
            `)}
            </tr>
            </tbody>
     </table>

The `AAA' column is rendered fine, but 'td' parts only show the 'aaa', the other 'td' are missing.
I've removed the whitespaces between tr tag, just not work, pls help.

woyodb commented 5 months ago

I got it. the problem this the tbody still have tr tag not included in a html`` function, so change to following will work:

        <tbody>
            ${html`
            <tr>
            ${html`<td>aaa</td>`}
            ${items.map(it=>html`
            <td>${`bbb_${it}`}</td>
            `)}
            </tr>
            `}
            </tbody>

Everything works fine now, except a little verbose. 😁

smalluban commented 5 months ago

You can avoid one of the ${}:

html`
  <tr>
    ${html`
      <td>aaa</td>
      ${items.map(it=>html`<td>${`bbb_${it}`}</td>`)}
    `}
  </tr>
`

I wish it could be simpler, but nowadays I strongly suggest using CSS Grid over tables - they have so many limitations.

Feel free to re-open if you have other issues with the subject.