Trees, Tree Tables, and Grids ... oh my

Hi everyone,


Background

I’m a Vaadin noob coming from Adobe Flex and am trying to figure things out so bear with me. I have a database, let’s say it is MySQL, with the following table structure.

State | City | NumericValue | and so on…


Sample Data

Virginia | City1 | 23
Virginia | City2 | 16
Maryland | City1 | 56
Maryland | City2 | 72
Maryland | City3 | 25
Texas | City1 | 14
Florida | City1 | 19
Florida | City2 | 26


Objective

What I would like to do is display the content in a grid/table format with the following.

  1. Group by State where the City with the highest NumericValue is displayed and all other cities are rolled up. The content changes so on the next update, the row would change so that the city with the highest value is always displayed.
  2. The row needs to have a color based on the NumericValue. I assume this is handled by CSS/SASS.
  3. The row needs to have a context menu.
  4. Double clicking the row needs to be actionable.

So using the sample data from earlier, the first criteria would have a table that looks like this…

Virginia | City1 | 23
Maryland | City2 | 72
Texas | City1 | 14
Florida | City2 | 26

As the content changes, specifically the NumericValue, the visible row will have the city with the highest value displayed with the cities having a lower value as a subrow (if that is the proper name). Hopefully that explains the first objective.


Question

Given the objectives listed above, which UI component is the proper one to use? Initially I thought the Grid component was the right choice, but I cannot find any grouping capabilities. Then I thought the Tree Table component was the one to use, but the database does not have a parent-child relationship (it is implied). So I am stuck; which UI is right and where can I find an example?

Thanks, Dave

By your objectives, you seem to be envisioning a pivot table. I don’t think any of the Vaadin UI components will support that directly.

No, not a pivot table, a table with rows rolled up. Let me try to explain a little better.


Normal Table

Virginia | City1 | 23
Virginia | City2 | 16
Maryland | City1 | 56
Maryland | City2 | 72
Maryland | City3 | 25
Texas | City1 | 14
Florida | City1 | 19
Florida | City2 | 26


Table with Row Grouping (Collapsed Groups)

Virginia | City1 | 23
Maryland | City2 | 72
Texas | City1 | 14
Florida | City2 | 26


Table with Row Grouping (Expanded Groups)

Virginia | City1 | 23
Virginia | City2 | 16
Maryland | City2 | 72
Maryland | City1 | 56
Maryland | City3 | 25
Texas | City1 | 14
Florida | City2 | 26
Florida | City1 | 26

So the first row (Virginia | City1 | 23) has a dropdown arrow to the left and rolls up, groups, or hides the rows under the group. This is how the Tree Table works when there’s a hierarchy. In my case, there’s just tabular data (no hierarchy - that is implicit). Hope that makes sense.

When you say something “rolls up”, you are definitely referring to a pivot table. If you just mean “expand and collapse” then perhaps a TreeTable would work although I’m not finding much documentation on that at the moment.

  1. TreeTable using a HierarchicalContainer to populate the data is the correct approach. The grouping of data needs to be done in your application logic. You don’t need to have an ID to map parent<->child relations, let me elaborate a bit more on how containers work. First you need to define your container and some properties for it

HierarchicalContainer container = new HierarchicalContainer(); container.addContainerProperty("state", String.class, null); ... add other properties After that, you can start populating it with items. An item is added using the addItem method. There are two variants which are most often used, addItem() without an argument and addItem(itemId). Item ID is a
ny object that uniquely identifies this particular item
, for example, it could be the object containing your city information (let’s call that class City).

Item item = container.addItem(city); item.getItemProperty("state").setValue(city.getState()); ... add values for other properties Now the “city” is the key for that given Item. Let’s say you want to add a second city, which is then a child element of the city that we just added. The only thing we need to do, is tell the container, that “anotherCity” is now a child of “city”.

Item item = container.addItem(anotherCity); // .. add values for properties container.setParent(anotherCity, city); Now all you need to do is create a logic of finding out which city should be the parent for which children.

  1. You need to apply a CellStyleGenerator for your table. The CellStyleGenerator is an interface you need to implement yourself. There’s a single method, getStyle which is called for every single cell in the table. You can thus define a CSS style name that is applied for the given cell (or row). To enable it, simply call treetable.setCellStyleGenerator(). I recommend first just trying it out and then using e.g. Chrome’s dev tools to insepct the DOM tree to see which CSS class name was actually applied to a cell, and then use that style name in your CSS. Also,
    see this post
    .

  2. For context menu, you can either use the built-in functionality in the core framework (which doesn’t support hierarchical context, only flat context). It’s called ActionHandler in the core framework. See the
    sampler for a demo and example code
    . Another option is to use the
    ContextMenu add-on
    , which allows you to also define hierarchical menus.

  3. To listen to click events in a table, apply a ItemClickListener (table.addItemClickListener(). You’ll receive an event object, which has isDoubleClick() method which can be used for checking, if the click event is a double click.
    NOTE!
    When double clicking, the browsers actually send three click events: single-click, single-click, double-click. You’ll notice this in your event listener. If isDoubleClick() returns true, you’ll can rely on it being a double click, but if it returns false, then you cannot be sure that it actual was a single click or if it’s an event sent before a double click. Yes, I know, this is quite crappy, but that’s how browsers send the events.

Kim,

I appreciate the lengthy/detailed response. That gives me an idea where to go from here. Let me see if I can figure things out given the information you provided. My fear with manually creating these hierarchies is performance. If I am updating the data every 3 seconds, then I am rebuilding the hierarchy manually in the code each time the data updates to display the highest city value as the parent.

Thanks, Dave