Closed jalberto closed 2 years ago
Try print html and template before set to DOM by console.log
I tried this and it works: https://liquidjs.com/playground.html#PHRhYmxlPgogIHslIGZvciBpdGVtIGluICgxLi4zKSAlfQogIDx0cj4KICAgIDx0ZD57e2l0ZW19fTwvdGQ+CiAgPC90cj4KICB7JSBlbmRmb3IgJX0KPC90YWJsZT4=,e30=
@harttle do you mean something like this?
const html = engine.parseAndRender(template, ctx);
result.innerHTML = html;
So I tried this and got an even odder result, I added strictVariables: true
to catch possible errors earlier.
const html = engine.parseAndRenderSync(template, ctx);
result.innerHTML = html;
If the for
is outside, a table
tag:
what happens inside a table
tag:
It seems complicated, could you create a minimal runnable snippet to demonstrate the problem? Then I can help.
I am using it inside Grist (https://www.getgrist.com/), as a custom widget, I cannot reproduce it in the playground, so I guess it can be affected by the iframe or Grist own JS, the custom part is the JS I added in the 1st comment.
I could create the same example in Grist and share it with you
That said, I wonder why it behaves different based on which tag is surrounding the code, is that expected?
Here is the env with public access: https://docs.getgrist.com/a8X5yeTvzGx2/Invoicing-copy
Here is the custom code: https://github.com/jalberto/grist-widget/tree/master/ja-invoices-es
I really appreciate any clue you may have. Thanks!
That said, I wonder why it behaves different based on which tag is surrounding the code, is that expected?
No, LiquidJS is HTML agnostic. It can be used to generate HTMLs and there's people who use LiquidJS to generate C++ code.
Please change this line:
to
console.log('template:', template, 'ctx', ctx);
const html = engine.parseAndRenderSync(template, ctx);
console.log('html', html);
and post the console log here.
template:
<h1>Factura</h1>
<section class="meta">
<div class="meta--invoice">
<table>
<tbody><tr>
<td>Número:</td>
<td>{{data.Number}}</td>
</tr>
<tr>
<td>Emitida:</td>
<td>{{data.Issued | date: "%d-%m-%Y"}}</td>
</tr>
<tr>
<td>Vencimiento:</td>
<td>{{data.Due | date: "%d-%m-%Y"}}</td>
</tr>
</tbody></table>
</div>
<div class="meta--client">
<ul>
<li>{{data.References.Client.Name}}</li>
<li>{{data.References.Client.Tax_ID}}</li>
<li>{{data.References.Client.Street1}}</li>
<li>{{data.References.Client.Street2}}</li>
<li>{{data.References.Client.Zip}} {{data.References.Client.City}}</li>
</ul>
</div>
<div class="meta--provider">
<ul>
<li>{{data.Invoicer.Name}}</li>
<li>{{data.Invoicer.Tax_ID}}</li>
<!-- <li>{{data.Invoicer.Street1}}</li> -->
<!-- <li>{{data.Invoicer.Zip}} {{data.References.Client.City}}</li> -->
</ul>
</div>
</section>
<section class="detaills">
{% for item in (1..3) %}
{% endfor %}
<table>
<tbody><tr>
<th>Concepto</th>
<th>Base unit.</th>
<th>Total</th>
</tr><tr>
<td>{{ item }}</td>
</tr></tbody></table>
</section>
<section class="misc">
<div class="misc--notes">{{data.Note}}</div>
</section>
<!-- Code injected by live-server -->
<script type="text/javascript">
// <![CDATA[ <-- For SVG support
if ('WebSocket' in window) {
(function() {
function refreshCSS() {
var sheets = [].slice.call(document.getElementsByTagName("link"));
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < sheets.length; ++i) {
var elem = sheets[i];
head.removeChild(elem);
var rel = elem.rel;
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
}
head.appendChild(elem);
}
}
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
var address = protocol + window.location.host + window.location.pathname + '/ws';
var socket = new WebSocket(address);
socket.onmessage = function(msg) {
if (msg.data == 'reload') window.location.reload();
else if (msg.data == 'refreshcss') refreshCSS();
};
console.log('Live reload enabled.');
})();
}
// ]]>
</script>
ctx {data: {…}}
widget.js?ver=1:21 html
<h1>Factura</h1>
<section class="meta">
<div class="meta--invoice">
<table>
<tbody><tr>
<td>Número:</td>
<td>JA-001</td>
</tr>
<tr>
<td>Emitida:</td>
<td>12-05-2022</td>
</tr>
<tr>
<td>Vencimiento:</td>
<td>12-06-2022</td>
</tr>
</tbody></table>
</div>
<div class="meta--client">
<ul>
<li>foo</li>
<li>foo</li>
<li>foo</li>
<li>foo</li>
<li>foo foo</li>
</ul>
</div>
<div class="meta--provider">
<ul>
<li>bar</li>
<li>fff</li>
<!-- <li>bar 9</li> -->
<!-- <li>333 foo</li> -->
</ul>
</div>
</section>
<section class="detaills">
<table>
<tbody><tr>
<th>Concepto</th>
<th>Base unit.</th>
<th>Total</th>
</tr><tr>
<td></td>
</tr></tbody></table>
</section>
<section class="misc">
<div class="misc--notes"></div>
</section>
<!-- Code injected by live-server -->
<script type="text/javascript">
// <![CDATA[ <-- For SVG support
if ('WebSocket' in window) {
(function() {
function refreshCSS() {
var sheets = [].slice.call(document.getElementsByTagName("link"));
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < sheets.length; ++i) {
var elem = sheets[i];
head.removeChild(elem);
var rel = elem.rel;
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
}
head.appendChild(elem);
}
}
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
var address = protocol + window.location.host + window.location.pathname + '/ws';
var socket = new WebSocket(address);
socket.onmessage = function(msg) {
if (msg.data == 'reload') window.location.reload();
else if (msg.data == 'refreshcss') refreshCSS();
};
console.log('Live reload enabled.');
})();
}
// ]]>
</script>
Note this part:
<section class="detaills">
{% for item in (1..3) %}
{% endfor %}
<table>
<tbody><tr>
<th>Concepto</th>
<th>Base unit.</th>
<th>Total</th>
</tr><tr>
<td>{{ item }}</td>
</tr></tbody></table>
</section>
{{ item}}
is outside of {% for %}
. I guess that's because when your HTML is rendered into DOM, it's normalized and additional <tbody>
element is added. So the template you get from DOM is no longer the one you set. Try add tbody in your source code.
Thanks! So yes, now the output is in the correct place, but the item still empty when called within table
tags
It seems the problem is the same :(
template:
<h1>Factura</h1>
<section class="meta">
<div class="meta--invoice">
<table>
<tbody><tr>
<td>Número:</td>
<td>{{data.Number}}</td>
</tr>
<tr>
<td>Emitida:</td>
<td>{{data.Issued | date: "%d-%m-%Y"}}</td>
</tr>
<tr>
<td>Vencimiento:</td>
<td>{{data.Due | date: "%d-%m-%Y"}}</td>
</tr>
</tbody></table>
</div>
<div class="meta--client">
<ul>
<li>{{data.References.Client.Name}}</li>
<li>{{data.References.Client.Tax_ID}}</li>
<li>{{data.References.Client.Street1}}</li>
<li>{{data.References.Client.Street2}}</li>
<li>{{data.References.Client.Zip}} {{data.References.Client.City}}</li>
</ul>
</div>
<div class="meta--provider">
<ul>
<li>{{data.Invoicer.Name}}</li>
<li>{{data.Invoicer.Tax_ID}}</li>
<!-- <li>{{data.Invoicer.Street1}}</li> -->
<!-- <li>{{data.Invoicer.Zip}} {{data.References.Client.City}}</li> -->
</ul>
</div>
</section>
<section class="detaills">
{% for item in (1..3) %}
{% endfor %}
<table>
<tbody>
<tr>
<th>Concepto</th>
<th>Base unit.</th>
<th>Total</th>
</tr><tr>
<td>{{ item }}</td>
</tr></tbody>
</table>
</section>
<section class="misc">
<div class="misc--notes">{{data.Note}}</div>
</section>
<!-- Code injected by live-server -->
<script type="text/javascript">
// <![CDATA[ <-- For SVG support
if ('WebSocket' in window) {
(function() {
function refreshCSS() {
var sheets = [].slice.call(document.getElementsByTagName("link"));
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < sheets.length; ++i) {
var elem = sheets[i];
head.removeChild(elem);
var rel = elem.rel;
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
}
head.appendChild(elem);
}
}
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
var address = protocol + window.location.host + window.location.pathname + '/ws';
var socket = new WebSocket(address);
socket.onmessage = function(msg) {
if (msg.data == 'reload') window.location.reload();
else if (msg.data == 'refreshcss') refreshCSS();
};
console.log('Live reload enabled.');
})();
}
// ]]>
</script>
ctx {data: {…}}
widget.js?ver=1:21 html
<h1>Factura</h1>
<section class="meta">
<div class="meta--invoice">
<table>
<tbody><tr>
<td>Número:</td>
<td>JA-001</td>
</tr>
<tr>
<td>Emitida:</td>
<td>12-05-2022</td>
</tr>
<tr>
<td>Vencimiento:</td>
<td>12-06-2022</td>
</tr>
</tbody></table>
</div>
<div class="meta--client">
<ul>
<li>foo</li>
<li>foo</li>
<li>foo</li>
<li>foo</li>
<li>foo foo</li>
</ul>
</div>
<div class="meta--provider">
<ul>
<li>bar</li>
<li>fff</li>
<!-- <li>bar 9</li> -->
<!-- <li>333 foo</li> -->
</ul>
</div>
</section>
<section class="detaills">
<table>
<tbody>
<tr>
<th>Concepto</th>
<th>Base unit.</th>
<th>Total</th>
</tr><tr>
<td></td>
</tr></tbody>
</table>
</section>
<section class="misc">
<div class="misc--notes"></div>
</section>
<!-- Code injected by live-server -->
<script type="text/javascript">
// <![CDATA[ <-- For SVG support
if ('WebSocket' in window) {
(function() {
function refreshCSS() {
var sheets = [].slice.call(document.getElementsByTagName("link"));
var head = document.getElementsByTagName("head")[0];
for (var i = 0; i < sheets.length; ++i) {
var elem = sheets[i];
head.removeChild(elem);
var rel = elem.rel;
if (elem.href && typeof rel != "string" || rel.length == 0 || rel.toLowerCase() == "stylesheet") {
var url = elem.href.replace(/(&|\?)_cacheOverride=\d+/, '');
elem.href = url + (url.indexOf('?') >= 0 ? '&' : '?') + '_cacheOverride=' + (new Date().valueOf());
}
head.appendChild(elem);
}
}
var protocol = window.location.protocol === 'http:' ? 'ws://' : 'wss://';
var address = protocol + window.location.host + window.location.pathname + '/ws';
var socket = new WebSocket(address);
socket.onmessage = function(msg) {
if (msg.data == 'reload') window.location.reload();
else if (msg.data == 'refreshcss') refreshCSS();
};
console.log('Live reload enabled.');
})();
}
// ]]>
</script>
The only way to make it work as expected is to wrap all the template in a scrtip
tag (it does not work with any other tag)
Works as expected, but
Produces this:
more context:
I also tried the
template
andresult
divs strategy, but I get same result. This is rendered inside an iframe, maybe is there some option I need to enable to make it work?