grist-core
grist-core copied to clipboard
Liquid support for widgets
Currently, it is possible to use LiquidJS to create a widget using Liquid, but is a bit cumbersome and unnatural as it requires to ass all the code into a scrtip tag.
Will be great to add native support to Liquid in Grist so files with liquid extension get to render natively y Grist.
This will make it much simpler to build custom widgets and will require fewer dependencies for simpler widgets.
It also opens the path to store custom widgets directly in Grist
Interesting idea @jalberto. One possibility might be to use the onEditOptions hook of custom widgets https://support.getgrist.com/widget-custom/#widget-options and write a single generic custom widget for liquid support, with an editing mode for the liquid code only, not the common html boilerplate. My colleague @berhalak wrote an even more generic custom widget like this that saved javascript html in the document as configuration, see an example in https://docs.getgrist.com/r6QRps5rKMj1/Jareks-fiddle-widget/m/fork The source code for that is in https://github.com/berhalak/my-widgets/
All that said, I'd be interested to hear more about your workflow, and how you'd see a polished liquid-supporting widget working. For files with a liquid extension, do you mean having attachments that are that kind of file render in some way, with fields filled from the row they are in?
I can see 2 uses cases:
- a way to bundle a widget (a single liquid file with css/html) into Grist, maybe using a specific DB to store it as liquid is design to be safe to store and just getting the required JS from Grist to access the records
- a liquid file (or the liquid itself) stored in a (hidden?) attribute or maybe as a formula, that will show the content of the row in a specific way
I am playing with the Invoicing template right now, and as a freelance, I may need to invoice to companies in different countries, and each one requires different format or detail ls or language, so to be able to customize each invoice individually add a lot of flexibility.
Right now, I am playing with this idea:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Grist Invoice</title>
<!-- A template for showing an invoice in a Custom Widget in Grist. -->
<script src="https://cdn.jsdelivr.net/npm/liquidjs/dist/liquid.browser.umd.js"></script>
<script src="https://docs.getgrist.com/grist-plugin-api.js"></script>
<script src="widget.js?ver=1"></script>
<link rel="stylesheet" href="widget.css?ver=1">
</head>
<body class="d-none">
<h2>Welcome to {{ data.Name | capitalize }}</h2>
</body>
</html>
document.addEventListener('DOMContentLoaded', () => {
var Liquid = window.liquidjs.Liquid
var engine = new Liquid({
extname: '.html',
cache: true
});
var src = document.body.innerHTML
grist.ready({requiredAccess: 'read table'});
grist.onRecord(function(record) {
var ctx = {
data: record
};
engine.parseAndRender(src, ctx)
.then(function(html) {
document.body.innerHTML = html
document.body.classList.remove('d-none')
});
});
})
It can become a new type of widget with only the liquid/css part editable and will all the JS already embedded to get access to the records or even to create custom forms.
<table>
{% tablerow i in (3..5) %}
{{ i }}
{% endtablerow %}
</table>
This simple snippet fails hard, do not render the rows and the content somehow sit outside table.
Similar oddities happen with every iterator in particular when used inside table (it works well with div thou.
I tried different way to render the result, but I cannot find what is happening. Using LiquidJs outside of Grist works as expected (ie in the official playground)
I wonder if something is creating a conflict or dying silently
It seems like Grist is somehow modifying the html once embedded, you can see here the logs: https://github.com/harttle/liquidjs/issues/504
Is that expected?
Could you make the https://docs.getgrist.com/a8X5yeTvzGx2/Invoicing-copy doc mentioned in that thread public?
No, I wouldn't expect Grist to touch anything within your custom widget, which is a distinct iframe.
Now public, the only way I found to make it work is to wrap everything in a script tag, but that is not ideal.
Thanks! Maybe you could narrow the problem down further by removing the grist parts and calling function(record) with a static record? Just for testing. Then you could view the page outside of Grist entirely.
I notice my browser isn't happy about the syntax of the page from a HTML perspective, don't know if that is relevant:
