A table display with dynamic # of columns

I need to be able to display a table, by parsing through the results returned in an XML.
Depending on the query that is input, the results returned in XML could contain different # of rows/columns.

Is there an example I could reference or can anyone suggest how I can do this? Or is there a way I can display a grid without associating the grid to a specific class?

I do not have Vaadin 14 example, but there is Vaadin 8 example of creating Grid with ArrayList instead of Bean for columns here


The API with Grid in Vaadin 14 is almost the same and both Vaadin 8 and Vaadin 14 operate with DataProvider in similar fashion. So the example should be applicable for the general parts.

You can use HashMap in similar fashion as ArrayList in the example too. That may be more suitable for you, if you have XML with properties with String as key.

Also note, that when you use HashMap or ArrayList, you will probably have issues with equals or hashCode, hence you need to override getId() in data provider in some suitable way, see example here


Again with HashMap you could have one property as “id”, in order to make the above work.

Thanks Tatu, will give it a shot and get back with further questions.

So, I finally got back to this module, and I realized that the data I get as input is a List<List> instead of get as xmlstring. So, your implementation is literally all I need. But one thing I don’t understand is why the need for the overriden getId()? I didn’t implement that, and the output I get id empty box. I know that the data is coming through fine, but could just missing the getId impl be the cause?

To identify unique rows, Grid and the underlying DataProvider require that the beans are either unique in the Java sense (hashCode and equals implemented properly) or the getId method of the DataProvider is overwritten. So yes, a missing getId may well be the cause.

Am not sure I understand how to implement the getId, sorry if that sounds nuts.
Does it mean I should incl one extra col in my result set that I could use as an id ? The # of rows/cols the grid will display is dynamic.

Does it mean I should incl one extra col in my result set that I could use as an id ?

That could be an easy way to do it, yes.

Still no luck, wondering if it’s because of how am trying to create & attach the grid to the layout? I need each cluster’s grid in a separate tab (which am trying to get using Accordion.

This is how am trying to implement the display of the grid (because the number of tabs is dynamic depending on the number of db clusters the results are being sought from):

//results is a Map<String, List<List<Object>>> object
Set<String> keys = results.keySet();

for(Iterator<String> it = keys.iterator(); it.hasNext();) {
	String tabName = it.next();
	VerticalLayout oneTabResults = new VerticalLayout();
	Grid<List<String>> resultsTable = createGrid(results.get(tabName));
	AccordionPanel tabPanel= new AccordionPanel(tabName, oneTabResults);

Grid creation itself is very similar to Tatu’s code:

private Grid<List<String>> createGrid(List<List<Object>> rows) throws ParserConfigurationException, SAXException, IOException, SQLException {
		Grid<List<String>> result = new Grid<>();
		List<List<String>> modifiedRows = new ArrayList<>();
		if(rows != null) {
			for(List<Object> row : rows){
				List<String> columnValues = new ArrayList<>();
				for(Object eachColumn : row) {
					Object value;
					value = Utils.getValue(eachColumn);
					columnValues.add(value != null ? value.toString() : "");
					//System.out.println(value != null ? value.toString() : "");
		MyDataProvider<List<String>> dp = new MyDataProvider<>(modifiedRows);
		return result;
	private class MyDataProvider<T> extends ListDataProvider<T> {

		public MyDataProvider(Collection<T> items) {
	    public String getId(T item) {
	        Objects.requireNonNull(item, "Cannot provide an id for a null item.");
	        if (item instanceof List<?>) {
	        	int idIndex = ((List) item).size();
	        	return ((List) item).get(--idIndex).toString();
	        } else {
	        	return item.toString();