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.
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);
}
}