Need help!

Hi, all. Programmers, i need your help. I looked through many docs about treegrid but still can’t understand how it works. I tried by myself but got some errors. Please, give nice example about it.

Thanks in advance!

Instead of clicking unlike you could answer the question.

Hey JavaVaadin Vaadinjava,

What errors did you get? What were you trying to accomplish?

Joacim Päivärinne:
Hey JavaVaadin Vaadinjava,

What errors did you get? What were you trying to accomplish?

Thanks for your feedback Joacim Päivärinne. I needed nice tutorial about treegrid, but couldn’t find a good one.

I could only create Treegrid Panel but culdnt’t add tree columns to it.

Here are a few examples:
https://vaadin.com/components/vaadin-grid/java-examples/treegrid

Adding columns is done via the addColumn method.

While we’re talking about Grid. How do I add “typeless” data to grid? This used to be possible with vaadin 7 table. I have 1-N columns that I generate on the fly. Grid<List> doesnt seem to work, it doesnt draw anything

You could use Grid<Map>, but then you’ll have to create the columns manually. Like here: https://vaadin8cookbook.blogspot.com/2017/04/grid-with-dates-as-columns.html

-Olli

Thank you all for your reply.
I will try to do it.

Thanks again.

JavaVaadin Vaadinjava:

Joacim Päivärinne:
Hey JavaVaadin Vaadinjava,

What errors did you get? What were you trying to accomplish?

Thanks for your feedback Joacim Päivärinne. I needed nice tutorial about treegrid, but couldn’t find a good one.

I could only create Treegrid Panel but culdnt’t add tree columns to it.

Sorry, i asked wrong. I need to add not columns but items.

I could add items using TreeDataProvider but cant give them title… it is written lib text but i want to give own Caption.
17472487.png

This is code

package com.mycompany.editormm;

import javax.servlet.annotation.WebServlet;

import com.vaadin.annotations.Theme;
import com.vaadin.annotations.VaadinServletConfiguration;
import com.vaadin.data.TreeData;
import com.vaadin.data.provider.TreeDataProvider;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.TreeGrid;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;

@Theme(“mytheme”)

public class MyEditor extends UI {

@Override


protected void init(VaadinRequest vaadinRequest) {
    
   
    VerticalLayout mainLayout = new VerticalLayout(); 
    
    
    mainLayout.setStyleName("main");
   
    
    mainLayout.setSizeFull(); 
   
   
    HorizontalSplitPanel main_Split = new HorizontalSplitPanel();
   
    
    main_Split.setStyleName("split");
   
   
    main_Split.setSplitPosition(15f);
    
  
    VerticalLayout leftSide = new VerticalLayout();
    
    
    leftSide.setStyleName("leftSide");
   
   
    VerticalLayout rightSide = new VerticalLayout();
   
    
    rightSide.setStyleName("rightSide"); 
    
    
    
    TreeGrid<Project> treeGrid = new TreeGrid<>();
   
    
    
    treeGrid.addColumn(Project::getName).setCaption("Column");
  
    
    
    
    TreeDataProvider<Project> dataProvider = (TreeDataProvider<Project>) treeGrid.getDataProvider();

    
   
    TreeData<Project> data = dataProvider.getTreeData();
    
   
    Project p = new Project("A");
   
    
    Project p1 = new Project("B");
   
    
    data.addItem(null, p);
   
    
    data.addItems(p, p1, new Project("C"));
    
   
    
    dataProvider.refreshAll();
    
    
    rightSide.addComponent(treeGrid);
    
   
    
    main_Split.addComponents(leftSide, rightSide);
    
    
    mainLayout.addComponent(main_Split);
    
    
    setContent(main_Split);

}

@WebServlet(urlPatterns = "/*", name = "MyEditorServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = MyEditor.class, productionMode = false)
public static class MyEditorServlet extends VaadinServlet {
}

}

Olli Tietäväinen:
You could use Grid<Map>, but then you’ll have to create the columns manually. Like here: https://vaadin8cookbook.blogspot.com/2017/04/grid-with-dates-as-columns.html

-Olli

The code on the page doesnt work with vaadin 10.0.6 or 12.0.3. with Java 1.8_181.
Error: Incorrect number of arguments for type Grid.Column; it cannot be parameterized with arguments <HashMap<LocalDate,String>, Object>

for code
Grid.Column<HashMap<LocalDate, String>, Object> column = grid.addColumn((ValueProvider<HashMap<LocalDate, String>,Object>)

Kimmo Parsama:

Olli Tietäväinen:
You could use Grid<Map>, but then you’ll have to create the columns manually. Like here: https://vaadin8cookbook.blogspot.com/2017/04/grid-with-dates-as-columns.html

-Olli

The code on the page doesnt work with vaadin 10.0.6 or 12.0.3. with Java 1.8_181.
Error: Incorrect number of arguments for type Grid.Column; it cannot be parameterized with arguments <HashMap<LocalDate,String>, Object>

for code
Grid.Column<HashMap<LocalDate, String>, Object> column = grid.addColumn((ValueProvider<HashMap<LocalDate, String>,Object>)

True, the addColumn API has changed a bit since then. You can drop the (ValueProvider<HashMap<LocalDate, String>,Object>) and just have a lambda expression there (or create an anonymous inner class if you wish).

I use vaadin 8. Only items are left for me to begin my project. i need hierarchy items…(treegrid not tree)

For example:

+Root

   +Item1

   -Item2

	   Item2A

	   Item2B

   +Item3

Like this. I checked a lot of docs though… Help please, if you have a simple example about it.

Thanks.

Olli Tietäväinen:

Kimmo Parsama:

Olli Tietäväinen:
You could use Grid<Map>, but then you’ll have to create the columns manually. Like here: https://vaadin8cookbook.blogspot.com/2017/04/grid-with-dates-as-columns.html

-Olli

The code on the page doesnt work with vaadin 10.0.6 or 12.0.3. with Java 1.8_181.
Error: Incorrect number of arguments for type Grid.Column; it cannot be parameterized with arguments <HashMap<LocalDate,String>, Object>

for code
Grid.Column<HashMap<LocalDate, String>, Object> column = grid.addColumn((ValueProvider<HashMap<LocalDate, String>,Object>)

True, the addColumn API has changed a bit since then. You can drop the (ValueProvider<HashMap<LocalDate, String>,Object>) and just have a lambda expression there (or create an anonymous inner class if you wish).

Thanks. I can now show the table and it draws as expected but if I click it, it explodes:


2019-01-18 10:31:35,140 ERROR [com.vaadin.flow.server.DefaultErrorHandler]
 - >
java.lang.RuntimeException: java.lang.IllegalStateException: Unkonwn key: 1
	at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:175)
	at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:130)
	at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.handleNode(PublishedServerEventHandlerRpcHandler.java:118)
	at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:64)
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:377)
	at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$0(ServerRpcHandler.java:367)
	at java.util.ArrayList.forEach(ArrayList.java:1257)
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:367)
	at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:309)
	at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:89)
	at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
	at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:1486)
	at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:300)
	at com.vaadin.flow.spring.SpringServlet.service(SpringServlet.java:65)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:728)
	at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:470)
	at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:356)
	at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:316)
	at org.springframework.web.servlet.mvc.ServletForwardingController.handleRequestInternal(ServletForwardingController.java:141)
	at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:177)
	at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:52)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:991)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:707)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:851)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:209)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:109)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:155)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:123)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:800)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:800)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1471)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Unkonwn key: 1
	at com.vaadin.flow.component.grid.Grid.findByKey(Grid.java:1995)
	at com.vaadin.flow.component.grid.Grid.select(Grid.java:1984)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:168)
	... 83 common frames omitted

Kimmo Parsama:
Thanks. I can now show the table and it draws as expected but if I click it, it explodes:

I did a quick test with Flow and this seems to work without issues:

List<Map<Integer, String>> items = new ArrayList<>();
// create 50 maps
for (int i = 0; i < 50; i++) {
	Map<Integer, String> map = new HashMap<>();
	// 10 values in each map, keys are 0..9
	for (int j = 0; j < 10; j++) {
		map.put(j, "column " + j + " row " + i);
	}
	items.add(map);
}

Grid<Map<Integer, String>> grid = new Grid<>();
// create columns 0..9 for grid
for (int i = 0; i < 10; i++) {
	Integer current = Integer.valueOf(i);
	grid.addColumn(map -> map.get(current)).setHeader("Column " + current);
}
grid.setItems(items);
grid.addSelectionListener(event -> {
	Notification.show("Selected " + (event.getFirstSelectedItem().isPresent() ? event.getFirstSelectedItem().get().get(0) : "nothing"));
});

Not sure what is going wrong with your Grid. My test was done with <vaadin.version>12.0.2</vaadin.version>.

Olli Tietäväinen:

Kimmo Parsama:
Thanks. I can now show the table and it draws as expected but if I click it, it explodes:

I did a quick test with Flow and this seems to work without issues:

List<Map<Integer, String>> items = new ArrayList<>();
// create 50 maps
for (int i = 0; i < 50; i++) {
	Map<Integer, String> map = new HashMap<>();
	// 10 values in each map, keys are 0..9
	for (int j = 0; j < 10; j++) {
		map.put(j, "column " + j + " row " + i);
	}
	items.add(map);
}

Grid<Map<Integer, String>> grid = new Grid<>();
// create columns 0..9 for grid
for (int i = 0; i < 10; i++) {
	Integer current = Integer.valueOf(i);
	grid.addColumn(map -> map.get(current)).setHeader("Column " + current);
}
grid.setItems(items);
grid.addSelectionListener(event -> {
	Notification.show("Selected " + (event.getFirstSelectedItem().isPresent() ? event.getFirstSelectedItem().get().get(0) : "nothing"));
});

Not sure what is going wrong with your Grid. My test was done with <vaadin.version>12.0.2</vaadin.version>.

Must be the autoupdating Im doing to the table then, try with this:


		runWhileAttached(table, new Runnable() {
			@Override
			public void run() {
				updateTableSeries(grid);
			}
		}, 1000, 1000);
		
	private void updateTableSeries(Grid<Map<Integer, String> > table) {
		
		List<Map<Integer, String>> items = new ArrayList<>();
		// create 50 maps
		for (int i = 0; i < 50; i++) {
			Map<Integer, String> map = new HashMap<>();
			// 10 values in each map, keys are 0..9
			for (int j = 0; j < 10; j++) {
				map.put(j, "column " + j + " row " + i);
			}
			items.add(map);
		}


		table.setItems(items);
	}
		
	public static void runWhileAttached(final Component component, final Runnable task, final int interval,
			final int initialPause) {
		// Until reliable push available in our demo servers
		UI.getCurrent().setPollInterval(interval);
		Command command = new Command() {
			private static final long serialVersionUID = 1L;

			@Override
			public void execute() {
				task.run();
			}
		};

		final Thread thread = new Thread() {
			@Override
			public void run() {
				try {
					Thread.sleep(initialPause);
					while (component.getUI() != null) {
						Future<Void> future = component.getUI().get().access(command);
						future.get();
						Thread.sleep(interval);
					}
				} catch (Throwable e) {
				}
			};
		};
		thread.start();
	}

This is slightly related issue https://github.com/vaadin/vaadin-grid-flow/issues/322

Maybe more than slightly related. One thing you could try is creating a wrapper object that provides proper hashCode and equals implementations.

I think I found the way to solve this. The problem in the end was that every time the table refreshed, the first click to the table failed with "unknown key: " exception but every click after that worked.

I noticed that after I added all the items to the table, the table.getDataCommunicator().getKeyMapper() didnt contain any entries. To fix this, I just looped through all the data in the table and called table.getDataCommunicator().getKeyMapper().key(row);.
Using this trick still doesnt work if the user clicks the table while the table is updating. Although Im not sure how big of an issue it is at that point.
In the end the update loop was like this:

private void updateTableSeries(Grid<TableRow> table) {

		....
		for(TableRow row: rows)
			table.getDataCommunicator().getKeyMapper().key(row);

}

Overall, it has been a very taxing experience trying to add this type of data to the table. This was very easy in Vaadin 7 and I don’t know why it couldn’t be made easy in Vaadin Flow. I really hope you add better support for this.

That does sound like a bug. If you have a reproducible sample, you should submit a ticket at https://github.com/vaadin/flow - I wasn’t able to make my test app break like that.

I agree that Vaadin 7’s data binding with Containers and Items was probably more suitable for completely arbitrary data types, but that seems to be a fairly uncommon use case. If you have any thoughts on how the API could be improved, those could be written in a ticket as well.

Anyway, good to hear you got it working at least!