Vaadin Table Example
In this Vaadin Table example, the following points are covered:
- Create the table
- Add the table to the page
- Populate the table
- Create a custom table header
- Create a custom table footer
- Calculate values for the table footer based on current rows
- Adding rows dynamically
- Deleting rows dynamically
- Selecting rows
- Unselecting rows
- Generate table cells from other cells
1. The tools
We are going to use:
- Eclipse Mars
- Vaadin 7.5.9.
2. Introduction
Vaadin Table is an easy to use and very dynamic widget, is commonly used to show tabular datasets, the data of the table is backed server side and the UI is updated using Ajax calls every time the data change.
3. Prerequisites
- Have JDK 8 installed
- Eclipse Mars installed
- Vaadin Plugin installed
- Vaadin Library installed
4. The actual code
4.1 Anotations
We begin by choosing a theme and a title for our example using Vaadin anotations:
Anotations
@Title("My UI") @Theme("valo")
Then we will create the main class and our init function, the init method is provided by Vaadin as an application starting point, the interface ColumnGenerator is used to calculate cells values:
Init method
public class VaadinTable extends UI implements Table.ColumnGenerator { @Override protected void init(VaadinRequest request) { setUpEventHandling(); setUpGui(); } }
4.2 Set up the GUI
Our GUI consist on two horizontal buttons and a table positioned vertically:
Layout
private Table characters; private Button buttonRemove; private Button buttonAdd; private VerticalLayout verticalLayoutMain; private HorizontalLayout horizontalLayoutButtons;
Initializing our widgets, set up two buttons and add it to a HorizontalLayout:
Initializing
buttonRemove = new Button("Remove", clickListenerRemoveButton); buttonAdd = new Button("Add", clickListenerAddButton); horizontalLayoutButtons = new HorizontalLayout(); horizontalLayoutButtons.addComponent(buttonAdd); horizontalLayoutButtons.addComponent(buttonRemove);
Create a Table with “Rising Swan Party” title and four columns, Race, Class, Level and Type:
Create the table
characters = new Table("Rising Swan Party"); characters.addContainerProperty("Race", String.class, null); characters.addContainerProperty("Class", String.class, null); characters.addContainerProperty("Level", Integer.class, null); characters.addContainerProperty("Type", Label.class, null); characters.addValueChangeListener(valueChangeListenrTable);
populate the table with five rows:
Populate the table
for(int i = 0; i < 5 ; i++) { generateCharacter(); }
This code set the table size to five rows long, allow you to select the rows in the table, send any change in the table data immediately to the server, make the footer visible and also add the titles to the footer:
Set table properties
characters.setPageLength(characters.size()); characters.setSelectable(true); characters.setImmediate(true); characters.setFooterVisible(true); characters.setColumnFooter("Race", null); characters.setColumnFooter("Class", "Sum of party levels");
add all components to the main layout and calculate the footer value:
Add components
verticalLayoutMain = new VerticalLayout(); setContent(verticalLayoutMain); verticalLayoutMain.addComponent(horizontalLayoutButtons); verticalLayoutMain.addComponent(characters); characters.setColumnFooter("Level", String.valueOf(calcSum()));
4.3 Set up event handling
To remove a row, it must be selected first and if is removed the column level is calculated and a notification is fired to alert the user:
Event handling
private void setUpEventHandling() { clickListenerRemoveButton = new Button.ClickListener() { private static final long serialVersionUID = 1L; @Override public void buttonClick(ClickEvent event) { Object selected = characters.getValue(); if(selected == null) { Notification.show("You must select an item"); } else { Notification.show("Value : " + selected); characters.removeItem(selected); characters.setColumnFooter("Level", String.valueOf(calcSum())); } } };
Add a row: first create a random row and when is added show a notification:
Add a row
clickListenerAddButton = new Button.ClickListener() { private static final long serialVersionUID = 1L; @Override public void buttonClick(ClickEvent event) { generateCharacter(); Notification.show("Added a row"); characters.setColumnFooter("Level", String.valueOf(calcSum())); } };
a notification is show when you select a row to note that you can do a lot of things at this point:
Select a row
valueChangeListenrTable = new ValueChangeListener() { private static final long serialVersionUID = 1L; @Override public void valueChange(ValueChangeEvent event) { Notification.show("Selected item : " + characters.getValue()); } }; }
Random data is created on the fly and added to the table:
Populate the table
private void generateCharacter() { Object newItemId = characters.addItem(); Item row1 = characters.getItem(newItemId); row1.getItemProperty("Race").setValue(getRace()); row1.getItemProperty("Class").setValue(getMyClass()); row1.getItemProperty("Level").setValue(getLevel()); row1.getItemProperty("Type").setValue(generateCell(characters, newItemId, "Level")); }
The sum of the “Level” column is calculated when needed:
Calculate the “Level” column
private int calcSum() { int sum=0; for(Iterator i = characters.getItemIds().iterator(); i.hasNext()) { int cID = (Integer) i.next(); Item item = characters.getItem(cID); int level = (int) item.getItemProperty("Level").getValue(); sum += level; } return sum; }
Choose a random option from a predefined list of options to fill the cells:
Random “Race” and “Class”
private String getRace() { int iRace = rnd.nextInt(races.length); return races[iRace]; } private String getMyClass() { int iClass = rnd.nextInt(myClasses.length); return myClasses[iClass]; }
A random number generated for the “Level” cell:
Random “Level”
private int getLevel() { return rnd.nextInt(19)+1; }
To fill a cell with a generated value is mandatory to override the method generateCell of the interface Table.ColumnGenerator
:
Cell generated value
@Override public Component generateCell(Table source, Object itemId, Object columnId) { Property prop = source.getItem(itemId).getItemProperty(columnId); if(prop.getType().equals(Integer.class) && prop != null) { int val = (int)prop.getValue(); Label customLabel = new Label(); if(val = 10 && val = 15 && val = 18) { customLabel.setValue("best"); } return customLabel; } return null; }
5. The Servlet
Vaadin runs on a servlet and need to be configured on the file web.xml:
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>VaadinTable</display-name> <servlet> <servlet-name>myservlet</servlet-name> <servlet-class> com.vaadin.server.VaadinServlet </servlet-class> <init-param> <paran-name>UI</param-name> <param-value>com.javacodegeeks.vaadin.table.VaadinTable</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>myservlet</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
6. The complete source code
VaadinTable.java
package com.javacodegeeks.vaadin.table; import java.util.Iterator; import java.util.Random; import com.vaadin.annotations.Theme; import com.vaadin.annotations.Title; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.Property.ValueChangeEvent; import com.vaadin.data.Property.ValueChangeListener; import com.vaadin.server.VaadinRequest; import com.vaadin.ui.Button; import com.vaadin.ui.Button.ClickEvent; import com.vaadin.ui.Button.ClickListener; import com.vaadin.ui.Component; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Table; import com.vaadin.ui.UI; import com.vaadin.ui.VerticalLayout; @Title("My UI") @Theme("valo") public class VaadinTable extends UI implements Table.ColumnGenerator { private static final long serialVersionUID = 1L; private Random rnd; private String[] races = {"Human", "Dwarf", "Elf", "Orc", "Halfling", "Durglor"}; private String[] myClasses = {"Paladin", "Warrior", "Archer", "Wizard", "Cleric", "Thief"}; private ClickListener clickListenerRemoveButton; private ClickListener clickListenerAddButton; private ValueChangeListener valueChangeListenrTable; private Table characters; private Button buttonRemove; private Button buttonAdd; private VerticalLayout verticalLayoutMain; private HorizontalLayout horizontalLayoutButtons; @Override protected void init(VaadinRequest request) { rnd = new Random(); setUpEventHandling(); setUpGui(); } private void setUpGui() { buttonRemove = new Button("Remove", clickListenerRemoveButton); buttonAdd = new Button("Add", clickListenerAddButton); horizontalLayoutButtons = new HorizontalLayout(); horizontalLayoutButtons.addComponent(buttonAdd); horizontalLayoutButtons.addComponent(buttonRemove); characters = new Table("Rising Swang Party"); characters.addContainerProperty("Race", String.class, null); characters.addContainerProperty("Class", String.class, null); characters.addContainerProperty("Level", Integer.class, null); characters.addContainerProperty("Type", Label.class, null); characters.addValueChangeListener(valueChangeListenrTable); for(int i = 0; i < 5 ; i++) { generateCharacter(); } characters.setPageLength(characters.size()); characters.setSelectable(true); characters.setImmediate(true); characters.setFooterVisible(true); characters.setColumnFooter("Race", null); characters.setColumnFooter("Class", "Sum of party levels"); verticalLayoutMain = new VerticalLayout(); setContent(verticalLayoutMain); verticalLayoutMain.addComponent(horizontalLayoutButtons); verticalLayoutMain.addComponent(characters); characters.setColumnFooter("Level", String.valueOf(calcSum())); } private void setUpEventHandling() { clickListenerRemoveButton = new Button.ClickListener() { private static final long serialVersionUID = 1L; @Override public void buttonClick(ClickEvent event) { Object selected = characters.getValue(); if(selected == null) { Notification.show("You must select an item"); } else { Notification.show("Value : " + selected); characters.removeItem(selected); characters.setColumnFooter("Level", String.valueOf(calcSum())); } } }; clickListenerAddButton = new Button.ClickListener() { private static final long serialVersionUID = 1L; @Override public void buttonClick(ClickEvent event) { generateCharacter(); Notification.show("Added a row"); characters.setColumnFooter("Level", String.valueOf(calcSum())); } }; valueChangeListenrTable = new ValueChangeListener() { private static final long serialVersionUID = 1L; @Override public void valueChange(ValueChangeEvent event) { Notification.show("Selected item : " + characters.getValue()); } }; } private void generateCharacter() { Object newItemId = characters.addItem(); Item row1 = characters.getItem(newItemId); row1.getItemProperty("Race").setValue(getRace()); row1.getItemProperty("Class").setValue(getMyClass()); row1.getItemProperty("Level").setValue(getLevel()); row1.getItemProperty("Type").setValue(generateCell(characters, newItemId, "Level")); } private int calcSum() { int sum=0; for(Iterator i = characters.getItemIds().iterator(); i.hasNext();) { int cID = (Integer) i.next(); Item item = characters.getItem(cID); int level = (int) item.getItemProperty("Level").getValue(); sum += level; } return sum; } private String getRace() { int iRace = rnd.nextInt(races.length); return races[iRace]; } private String getMyClass() { int iClass = rnd.nextInt(myClasses.length); return myClasses[iClass]; } private int getLevel() { return rnd.nextInt(19)+1; } @Override public Component generateCell(Table source, Object itemId, Object columnId) { Property prop = source.getItem(itemId).getItemProperty(columnId); if(prop.getType().equals(Integer.class) && prop != null) { int val = (int)prop.getValue(); Label customLabel = new Label(); if(val = 10 && val = 15 && val = 18) { customLabel.setValue("best"); } return customLabel; } return null; } }
7. Running the example
At this point you can run the example on Tomcat inside eclipse using right click on the project and then Run As -> Run on Server:
As a result you get a table where you can add rows delete rows, order rows and resize columns which under the hood use Javascript,css and html with just a few lines of Vaadin Java magic.
8. Download the source code
This was an example about Vaadin Table.
You can download the Eclipse project here: VaadinTable