Enterprise Java

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:

Figure 1. Run Vaadin aplication
Figure 1. Run Vaadin aplication

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.

Figure 2. Vaadin Table results
Figure 2. Vaadin Table results

8. Download the source code

This was an example about Vaadin Table.

Download
You can download the Eclipse project here: VaadinTable

Jesus Boadas

I'm a self taught programmer, I began programming back in 1991 using an IBM A10 mainframe with Pascal an Assembler IBM 360/70 emulator and Turbo C on a X86 PC, since that I work for the banking industry with emerging technologies like Fox Pro, Visual Fox Pro, Visual Basic, Visual C++, Borland C++, lately I moved out to the Airline industry, leading designing and programming in-house web applications with Flex, Actionscript, PHP, Python and Rails and in the last 7 years I focused all my work in Java, working on Linux servers using GlassFish, TomCat, Apache and MySql.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button