What kinds of Data Model does the library provide?

Currently there are following kinds of data models:

  • Editable model (grid)
  • Hierarchcal model (grid)
  • Tree model (grid)
  • Lazily Loadable model (grid, suggestion box)
  • List model (combo box, suggestion box)

In fact most of data model implementations implement several types. Typical samples are

  • EditableGridDataModel. This class implements Editable and LazyLoadable interfaces.
  • LazyGridDataModel. This class implements Editable and LazyLoadable interfaces.
  • HierarchicalGridDataModel. This class implements Editable and Hierarchical interfaces.
  • LazyHierarchicalGridDataModel.This class implements editable, hierarachical and lazy interfaces.
  • TreeGridDataModel.This class implements editable and tree interfaces.
  • LazyTreeGridDataModel.This class implements editable, tree and lazy interfaces.

In some cases you can also use combined models. For instance if you have a Hierarchical Grid you can put a Tree Grid into the first one.


What is the Simple Data Model?

SimpleDataModel is a basic class for all non-hierarchical non-editable models. You can instantiate it, but there is no any widget where you can apply it. This class is kept for future improvements.


What is the Editable Data Model?

EditableGridDataModel is a widely used implementation. It was developed especially for the EditableGrid. Sample below shows how you can instantiate it.

//create a new grid
EditableGrid grid = new EditableGrid(
   new String[]{"First Name","Surname"},
   new Class[]{LabelCell.class, LabelCell.class}

The sample illustrates how put data in the model. Note that "data" in this context means a two-dimension array of abstract objects. In common case Objects can be not only strings but numbers, dates and even other GWT widgets. And it's a reason data models are not serializable.

This sample constructs a model that doesn't allow lazy loading of data with AJAX. You can change the data programmatically but you still have to worry about view and model synchronization in this case.


What is the Hierarchical Data Model?

Hierarchical data model allows to store related entities. It's designed for the Hierarchical Grid widget. The sample below illustrates how to create a simple hierarchy.

//create a new model containing employees
Editable model = new EditableGridDataModel(
   new Object[][] {
       new String[]{"John","Doe"},
       new String[]{"Piter","Walkman"},
       new String[]{"Rupert","Brown"}

//create a new model containing departments
HierarchicalGridDataModel hierarchicalModel = new HierarchicalGridDataModel(
   new Object[][] {
       new Object[]{"Accountants",new Integer(3)},
       new Object[]{"Management",new Integer(10)},
       new Object[]{"Development",new Integer(100)}

//make a relationship between Accountants department and a list of employees
hierarchicalModel.addSubgridModel(0,0, model);

Note that the hierarchical model is not just a tree structure. It's more complicated. For example you can make a relationship not only between a concrete parent entity and a list of child entities. Grid cells can contain more complex entities like widgets and therefore you can link a submodel to a particular cell. In fact this functionality is limited by the Hierarchcal Grid widget to simplify development, but you are able to design your own grid and reuse the same model in more flexible way.


What is the Tree Data Model?

Tree Data Model is an extension of the Editable Data Model that allows describing tree structures. It contains additional methods which help working with branches of this tree. The sample below illustrates how to fill the model with structured data.

//create a new model and add one root item
TreeGridDataModel model = new TreeGridDataModel(new Object[][]{new String[]{"President"}});

//create second level items
TreeGridRow president = (TreeGridRow) model.getRow(0);
model.addRow(president,new String[]{"Financial Department Director"});
model.addRow(president,new String[]{"Marketing Department Director"});
model.addRow(president,new String[]{"Chief Security Officer"});
model.addRow(president,new String[]{"Development Department Director"});

//create third level items for the first department
TreeGridRow financialDirector = model.getRow(president,0);
model.addRow(financialDirector,new String[]{"Accountant"});
model.addRow(financialDirector,new String[]{"Financial Manager"});

//create third level items for the second department
TreeGridRow marketingDirector = model.getRow(president,0);
model.addRow(marketingDirector,new String[]{"Brand Manager"});
model.addRow(marketingDirector,new String[]{"Sales manager"});
model.addRow(marketingDirector,new String[]{"Promouter"});

//create third level items for the last department and configure paging
TreeGridRow developmentDirector = model.getRow(president,0);
model.addRow(marketingDirector,new String[]{"Database Developer"});
model.addRow(marketingDirector,new String[]{"UI Developer"});
model.addRow(marketingDirector,new String[]{"Support Engeneer"});
model.addRow(marketingDirector,new String[]{"Tester"});

This sample creates a new Tree Data Model and fills it with the data. Additionally it enables paging for particular nodes.


What is the Lazy Data Model?

Lazy Data Model is useful if you need server side data loading, paging and sorting. This model implements the org.gwt.advanced.client.datamodel.LazyLoadable interface. If fact it's an extension of the Editable Data Model, but it tries to "cheat" a grid returning greater total row count then the model contains. Look at the next sample to understand how it works.

LazyLoadable model = new LazyGridDataModel(
   new DataModelCallbackHandler() {
       public void synchronize(GridDataModel model) {
           // get removed rows
           Object[][] removedRows = ((Editable) model).getRemovedRows();

           // delete data from the storage

           // clear old information
           ((Editable) model).clearRemovedRows();

There are two important things in this listing. The first one is that we set a total row count directly. The second one is that we defined a data model callback handler. It's a best practise to use callback handlers with lazy models. Otheriwse grid content will never be refreshed on page change, sorting, etc. Note also that we set a total row count in the synchronize() method. It's a best practise as well.


How does data synchronization work?

Data synchronization is an important option of the data models. There are two types of synchronization available:

  • client side
  • server side

To enable data synchronization you should set a data model callback handler as it has been illustrated in What is the Lazy Data Model?. To use client side synchronization you should create a simple Editable data model. Note that in this case paging and sorting will be done automatically by the model on client side. In case of lazy loading you will have to do it using server side tools (usually database queries). Every time when a grid decides that synchronization is required, it invokes the synchonize() method. It may happen on the following events:

  • Save button pressed
  • Page changed
  • Sorting order / column changed

When you implement the callback handler you should take into account that it must not only load data but save it in the persistence storage, delete rows and do other synchronization actions. But if you use client side synchronization you can do it not in the handler but on save event like it shown in the next sample.

GridPanel panel = new GridPanel();
// initialize the panel here

// add custom listener
panel.getMediator().addGridListener(new GridListenerAdapter() {
   public void onSave(GridDataModel dataModel) {
       //do synchronization

Sometimes it can be much simpler then handler implementation.


How to develop a custom callback handler?

To develop a custom data model callback handler you should implement the org.gwt.advanced.client.datamodel.DataModelCallbackHandler interface. Note that "synchronization" means that your handler should load data, fill the model, update and remove rows in the persistence storage, etc. Remeber, that the model passed into the synchronize() method contains not only actual rows but also contains a list of removed rows. These rows can be obtained using the Editable.getRemovedRows() method.

// get removed rows
Object[][] removedRows = ((Editable) model).getRemovedRows();

// delete data from the storage

// clear old information
((Editable) model).clearRemovedRows();

Don't forget to clear history. Otherwise your handler will try to remove the same rows from the persistence storage every time when synchronization required.


What is locking and why is locking mandatory if I use server side synchronization?

Locking is a mechanism that prevents asynchronous data changes in the grids rised by a user. You can use locking in any place of your application every time you want to lock advanced GWT widgets controls. As soon as you locked the screen and finished necessary actions, you should unlock it.

Don't forget to do this step and note that on unlock event grid content will be refreshed. So, if you use callback handlers to synchronize data, you can lock and unlock a particular grid from these handlers. And no any other actions required to refresh the grid after synchronization.

public class MyHandler implements DataModelCallbackHandler {
   private GridPanel panel;

       public MyHandler(GridPanel panel) {
           this.panel = panel;

       public void synchronize(GridDataModel model) {
           //lock the grid panel
           try {
               // synchronize data here
           } finally {
               // unlock the panel and refresh grid content

In case if you don't use callback handlers, locking is not required and content will be refreshed automatically.


What are data model events?

Every time the model is changed it sends an event that is handled by the EventMediator class. This class invokes appropriate methods of the grid widget and makes it update the view.

You can also use the events to do application specific operations on data change. Everything you need is to implement the EditableModelListener interface and register your implementation using the EditableGridDataModel.addListener() method.