True, this is hard to use in the renderhtml
(HTML Viewer) widget. It is possible already with some effort, and I put an example here:
https://public.getgrist.com/mSxCywdTTSJa/Attachments-in-HTML-Viewer/p/1#a1.s1.r1.c2
-
Firstly, since you need to run JS, there is a hidden way to allow that in the
renderhtml
widget. Use the widget by choosingCustom URL
option, and use the URL ofhttps://gristlabs.github.io/grist-widget/renderhtml?tags=script
. (Thetags=script
option allows<script>
tags in the HTML to be rendered.) -
Second is you need a fairly sophisticated formula that combines Python and Javascript. The one in the example is this:
setImageSrcScript = """ <script> grist.docApi.getAccessToken({readOnly: true}) .then(tokenInfo => { for (let img of document.querySelectorAll('img')) { if (img.dataset.att) { img.src = `${tokenInfo.baseUrl}/attachments/${img.dataset.att}/download?auth=${tokenInfo.token}`; } } }) </script> """ return """ <div style="padding: 24px; background-color: #F4F0FF"> {setImageSrcScript} <h1>{Company}</h1> <p>Hello world! {att} </div> """.format( setImageSrcScript=setImageSrcScript, Company=$Company, att='\n'.join('<p><img data-att="{}" width="100%">'.format(att.id) for att in $Attachments) )
The setImageSrcScript
part is meant to be reusable with no changes in other such image-rendering formulas; it goes through all <img>
tags with data-att
attribute equal to the id
of an attachment, and adds a suitable src
tag for those.
As for a better approach, the problem with using base64 encoding in a formula to compute HTML that includes the full body of attachments is that it can produce very large formula results. Grist doesn’t handle those very efficiently. For a large table, it could quickly become a problem. I think a more promising approach would be an improvement to the HTML Viewer
widget that automatically does something similar to what’s done by the setImageSrcScript
above.