squirrellyjs / squirrelly

Semi-embedded JS template engine that supports helpers, filters, partials, and template inheritance. 4KB minzipped, written in TypeScript ⛺
https://squirrelly.js.org
MIT License
634 stars 83 forks source link

Strange bug #131

Closed franckobe closed 4 years ago

franckobe commented 4 years ago

Describe the bug Uncaught ReferenceError: hvals is not defined when trying to display a td, but not with a li

To Reproduce https://codepen.io/franckobe/pen/XWWYXZK

You can test with buttons a working case and a not working case. I don't understand the reason.

Thanks

Extra comment It seems to be with tables, when i try to put an if aroud a tr it is not interpreted

nebrelbug commented 4 years ago

@franckobe thanks for submitting an issue!

For some reason, running

document.getElementById("notWorking").innerHTML;
console.log(template)

outputs:

<h1>Dossier n°{{ dossier.numDossier }}</h1>

{{ each(options.dossier.conteneurs) }}

{{ /each }}
<table class="table table-xs table-hover">
<thead>
<tr>
<th>Conteneur</th>
</tr>
</thead>
<tbody><tr>
<td>{{ @this.numConteneur }}</td>
</tr></tbody>
</table>

Which means there seems to be an issue with the HTML template element rather than Squirrelly

nebrelbug commented 4 years ago

I'll try to look into this more later tonight

nebrelbug commented 4 years ago

See: https://stackoverflow.com/questions/58775831/js-get-html-template-innerhtml-with-table-content-fails/58775887#58775887

Apparently, you can't have plain text inside a tbody, so the parser errors. I'd recommend using a <script> tag instead of a <template> tag.

Example:

<script id="big-template" type="text/x-squirrelly-template">
    <table>
..............
    </table>
</script>

Let me know if this helps!

nebrelbug commented 4 years ago

Closing this :)

Here's a working demo with the fix: https://codepen.io/nebrelbug/pen/wvvxOwK

franckobe commented 4 years ago

Ok thank you ! I find the script tag less intuitive than template tag for templating but no choice.

I had another example, like the following example that worked, that's why i didn't understand. But now this is clear, only html tags in table tags. I didn't think that html parser block the execution like this.

<tbody>
    <template>
        {{ each(options.commandes) }}
            <tr>
                 <td>{{ @this.reference }}</td>
                 <td>{{ @this.datePriseEnCharge }}</td>
            </tr>
         {{ /each }}
      </template>
</tbody>

Thanks for your work !

StefanJelner commented 2 years ago

Thanks for the advice! Today i stumbled upon the same problem, using template tags together with tables. Browsers parse the content of template tags as HTML and text nodes between some elements are considered malformed and therefore placed outside the table, leading to the squirrelly template being broken. The solution is a script tag.

One of the drawbacks using a script tag is, that syntax highlighting is usually lost. But there is an easy solution to that: Just add type="text/html".

Example:

<script type="text/html" id="squirrelly">
    <table>
        {{@each(it.rows) => row}}
            <tr>
                {{@each(row.columns) => column}}
                    <td>{{column}}</td>
                {{/each}}
            </tr>
        {{/each}}
    </table>
</script>

Works like a charm in VSC. Another advantage is, that you do not have to do complicated fiddling with DocumentFragment and HTML decoding, but just use innerHTML:

document.getElementById('squirrelly').innerHTML