Blog

Vaadin 7.5 - Grid Extensions

By  
Teemu Suo-Anttila
·
On Jul 6, 2015 8:00:00 AM
·

Vaadin 7.5 - Grid Extensions

Vaadin 7.5 brought some new visible features for the Grid component, but there was also another big, not so visible, change. In Vaadin 7.5, there is now a new abstract base class AbstractGridExtension that contains helpers for Grid extensions. It contains functionality for mapping client-side row and column information to their server-side counterparts. This feature makes catching and sending events from the client to the server very easy and useful.

 

Something as simple as catching a context click and providing relevant information on it to the server-side is not supported in Grid out-of-the-box. However, the extension to do it is not that complex.

 

Communication

Since this event contains information that needs to be sent from the client to the server, we need to implement a ServerRpc for this to work.

public interface ContextClickRpc extends ServerRpc {
  public void contextMenu(String rowKey, String columnId, 
    MouseEventDetails mouseDetails);
}

There are a couple of things to note. First of all are the two String values. rowKey and columnId are something that GridConnector knows about Items and Columns. These are transported as String variables, since the server-side is able to map those correctly. There is also MouseEventDetails which has the relevant coordinates and buttons of the mouse click for the event.

 

The server-side implementation

The structure of the server-side part of the extension is easy to do. Basically what is needed is a way to extend a Grid instance, and implement the RPC from above.

 
public class ContextClickExtension extends AbstractGridExtension {
  private ContextClickExtension(final Grid grid) {
    super(grid);
    registerRpc(new ContextClickRpc() {
      @Override
      public void contextClick(String rowKey, 
        String columnId, MouseEventDetails details) {
        fireEvent(new ContextClickEvent(grid, 
          getItemId(rowKey), getColumn(columnId), details));
      }
    });
  }

  public static ContextClickExtension extend(Grid grid) {
    return new ContextClickExtension(grid);
  }
}

This extension fires a ContextClickEvent, which is basically an extended version of ItemClickEvent. It occurs when receiving a message from the client-side through the RPC.

 

The constructor is done as a private and the primary way for actually extending a Grid is to use the static extend method:

 
Grid myGrid = new Grid();
ContextClickExtension.extend(myGrid);

The client-side implementation

The client-side implementation is the one that does most of the heavy lifting in this example. In the connector class, you will need to override a method called extend, and that’s where the magic actually happens.

 
@Override
protected void extend(ServerConnector target) {
  final Grid
          
            grid = getGrid();
  grid.sinkBitlessEvent(BrowserEvents.CONTEXTMENU);
  grid.addHandler(new ContextMenuHandler() {
    @Override
    public void onContextMenu(ContextMenuEvent event) {
      EventCellReference
           
             cell = grid.getEventCell();
      if (!cell.isBody()) {
        return;
      }
      event.preventDefault();
      ContextClickRpc rpc = getRpcProxy(ContextClickRpc.class);
      rpc.contextMenu(getRowKey(cell.getRow()),
        getColumnId(cell.getColumn()),
        getMouseEventDetails(event.getNativeEvent()));
    }
  }, ContextMenuEvent.getType());
}

           
          

This implementation only informs the server about context clicks that happen in the body of the Grid. Headers and footers still open the context menu of the browser.

 

It is important to sink the correct events for Grid, so those will get handled. A handler is added to take care of the event when it happens and prevent the default functionality of the browser. The most important thing is that the information is sent through RPC to the server.

 

This example is not complete, as it is missing some key parts, like the implementations of the methods getGrid, getRowKey and getColumnId. These methods basically access the parent connector, called GridConnector, of the extension and retrieve relevant data from it.

 

What to do next

You can check out this extension in my GridExtensionPack add-on in the directory. This add-on contains an AbstractGridExtensionConnector helper class with most helper methods immediately available, two Grid extensions and a PagedContainer for the Grid. The add-on code aims to be as clear an example as possible while providing useful extensions for the Grid component. The source code is available on Github.

 
 
Teemu Suo-Anttila
Teemu Suo-Anttila has been at Vaadin since 2013. He is a Vaadin Expert working with the development of the Vaadin Framework. His speciality is the Grid component.
Other posts by Teemu Suo-Anttila