Vaadin 24 - Grid Render HTML

Hi Guys - again, I’m sure I’m just missing something stupid - but I’ve looked over the docs on the grid - and there is no obvious way (that I have found) to render HTML (that’s in the database column) in the grid view.

Any gentle nudge in the right direction would be greatly appreciated!

new Html(string)

You mean, something like this?:

grid.addColumn(new ComponentRenderer(row → new Html(row.getMyHtml())));

I haven’t seen any sensible alternatives, but isn’t ComponentRenderer supposed to be a bit heavy, since the server-side must track every instance it creates?

Btw: If you want to output escaped text with some static html decoration, you can use LitRenderer:

grid.addColumn(LitRenderer.of(“${item.text}”).withProperty(“text”, Row::getText));

(haven’t used this yet, but assume I will need it soon, so I googled)

Lit won’t allow usage of html like this. You have to use .innerHTML=${item.text} - yes, lit renderer would perform better, but I had the feeling this would be a bit overwhelming to begin with

@empathetic-hippo - THANK YOU! I was playing all around that - so thanks very much for the correct syntax. My column has HTML from TinyMCE (from another application) - and I’m getting an error:
java.lang.IllegalArgumentException: HTML must contain exactly one top level element
A sample of the HTML looks like this:
<html><body><p><span style="font-size: 12pt; font-family: 'times new roman', times;">The billing matrix for this study has been sent. Please verify that the corresponding PRL record has been created.</span></p> <p><span style="font-size: 12pt; font-family: 'times new roman', times;">If this is an Initial Specification and Budget Version (both should read Version 1), <strong>no action</strong> is needed.</span></p> <p style="margin: 0in; font-family: Calibri; font-size: 11.0pt;"><span style="font-family: 'times new roman', times; font-size: 12pt;">If you have any questions about this notification, please reply to this email.</span></p> <p><span style="font-family: 'times new roman', times; font-size: 12pt;">Thank you</span></p></body></html>

From what I can see - there is only on “top level element” - the <html></html> element (??)

If you want a couple of choices: Dynamic HTML using a Vaadin LitRenderer - Stack Overflow

If you want to add HTML with a html root tag, you probably want to use an iframe since it’s incorrect ( from an html point of view) to have 2 html tags in a page.

( iframe with the attribute srcdoc: HTML iframe tag)

Or you should clean up your html :slightly_smiling_face:

:slightly_smiling_face: Thanks - I get that. The TinyMCE is TERRIBLE at the HTML. I can’t really change the HTML - since it’s also used by another application… I really appreciate the tip!

TinyMCE is great, the Html component in Vaadin is not that great with its limitation :wink:

I suggest to look into RichText component in Viritin. That eats all HTML TinyMCE can create. Here with adjusted JSoup SafeList:

    RichText richText = new RichText() {
        @Override
        public Safelist getSafelist() {
            return Safelist.relaxed()
                    .addAttributes("span", "style")
                    .addAttributes("p", "style");
        }
    };

If you want absolutely best performance and can trust the html source, you could also abuse the CustomLayout component in the same add-on. That skips all validations for the inputted HTML. Extra html or body tags don’t matter there either, browsers will gracefully strip those away:

    CustomLayout customLayout = new CustomLayout();
    customLayout.setTemplate("<html><body><p><span style=\"f....

I would be surpriced if using Lit based solution is faster than the above.

This actually look like something we have in our own app, which we have not fixed yet, since we are in Vaadin8; We produce html emails, store them in a table, and later want to display sent emails in our app.
I guess this means we will also be needing this eventually.

If you can trust the html to always have the same structure (ie if you have generated it in the first place), I would just trim it;

new Html(row.getMyHtml().replace(“”, “”).replace(“”))

Maybe check for null and do it with a regexp instead