Uwe Allner
Uwe Allner

Reputation: 3467

Vaadin 24 Grid refuses to render Column with ComponentRenderer

I am using Vaadin 24.2.3 and Java 17. Browser is mostly Chrome, but also tried with others.

I am trying to render a Grid with two Columns, one of them should render multi line text. My data provider delivers the correct values, the first column is rendered correctly; but so far for the second column either I do get just one single line of text or a completely empty output.

        ...
        Grid<JobMessageDetail> messageGrid = new Grid<>(JobMessageDetail.class, false);
        messageGrid.setWidthFull();
        messageGrid.setItems(filterDataProvider);
        messageGrid.addColumn(JobMessageDetail::getIdentifier)
                .setHeader("Identifier").setWidth("5em");  // rendered correctly

    // Variant one: results in one single line with all HTML tags rendered as text
        messageGrid.addColumn(
                LitRenderer.<JobMessageDetail>of("${item.messages}")
                .withProperty("messages", JobMessageDetail::getMessagesAsString))
            .setHeader("Messages").setWidth("50em");

    // Variant two: results in JavaScript error 
    // "There seems to be an error in Vaadin Grid: cannot read properties of undefined (reading 'getbynodeid')"
        messageGrid.addColumn(new ComponentRenderer<>(
                i -> {
                    Html result =  new Html(i.getMessagesAsString());
                    result.setId(String.valueOf(UUID.randomUUID()));
                    return result;
                }
                ))
            .setHeader("Messages").setWidth("50em");
    // Variant three: results in no content at all, even with fixed String list
        messageGrid.addColumn(LitRenderer.<JobMessageDetail>of(" <unsafe-html-component .html=${item.html}></unsafe-html-component>")
                .withProperty("html", i -> {
                    List<String> strings = List.of("item 1", "item 2", "item 3");
                    String listItems = "";
                    for (String eventItem : strings) {
                        listItems += "<li>"+eventItem +"</li>";
                    }
                    return listItems;
                }))
                .setHeader("Messages").setWidth("50em");

The value class JobMessageDetail:

@Getter
@Setter
@AllArgsConstructor
public class JobMessageDetail {
    private String identifier;
    private List<JobMessage> messages;

    public String getMessagesAsString() {
        return "<div>" + messages.stream()
                .map(x -> StringUtils.join("<b>", x.getMessageCode(), "</b>: ", x.getProperties()))
                .collect(Collectors.joining("<br>\n")) + "</div>";
    }
}

According to the JavaScript message I am completely lost how to fix; most of the solutions for multi line columns available are for Vaadin 14 or earlier, which are not applicable any more.

What am I missing or doing wrong? Which way to go for multi line columns? This issue seems not to be too exotic.

EDIT: I was able to enhance variant one by setting

messageGrid.addThemeVariants(GridVariant.LUMO_WRAP_CELL_CONTENT);

Now the text is wrapped, but I am not able to define where. Neither \n nor <br> does the job. Is it possible somehow?

EDIT 2: It seems, that Spring Java Live Reload gets in conflict with Vaadin ColumnRenderes. As I have removed the dependency for it, the ComponentRenderer works as expected. Maybe I should report that as a bug to the Vaadin team.

Upvotes: 0

Views: 500

Answers (1)

ollitietavainen
ollitietavainen

Reputation: 4290

With default styles, a Html component should be enough, with GridVariant.LUMO_WRAP_CELL_CONTENT. You can use <br> where you want line breaks. Example:

package com.vaadin.starter.skeleton;

import com.vaadin.flow.component.Html;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.grid.GridVariant;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * The main view contains a button and a click listener.
 */
@Route("")
public class MainView extends VerticalLayout {

    public static class JobMessageDetail {
        private List<String> messages = new ArrayList<>();

        public JobMessageDetail(String s) {
            Random random = new Random();
            int count = random.nextInt(8) + 2;
            for (int i = 0; i < count; i++) {
                if (i == 1) {
                    messages.add("This is a very long long long long long long long<br> long long long long long line");
                } else {
                    messages.add(s + i);
                }
            }
        }

        public String getMessagesAsString() {
            return "<div>" + messages.stream()
                    .map(x -> StringUtils.join("<b>", x, "</b>: ", "1,2,3"))
                    .collect(Collectors.joining("<br>")) + "</div>";
        }
    }

    public MainView() {
        setSizeFull();
        Grid<JobMessageDetail> grid = new Grid<>();
        grid.setSizeFull();
        grid.setItems(new JobMessageDetail("foo"), new JobMessageDetail("bar"), new JobMessageDetail("baz"), new JobMessageDetail("quux"));
        grid.addColumn(s -> s).setHeader("First");
        grid.addComponentColumn(s -> new Html(s.getMessagesAsString()));
        grid.addThemeVariants(GridVariant.LUMO_WRAP_CELL_CONTENT);
        add(grid);
    }


}

enter image description here

Upvotes: 1

Related Questions