Showing extra data for Grid rows

Some data might not be suitable to be shown as part of a regular Grid, e.g. because it’s too large to fit into a Grid cell or because it’s secondary information that should only be shown on demand. This kind of situation is covered with the row details functionality that shows a Vaadin Component in an area expanded below a specific row. Using this functionality is a two step process: first you need to implement a generator that lazily creates the Component for a row if it has been expanded, and then you need to hook up the events for actually expanding a row.

This example uses the same data as in the Using Grid with a Container example.

DetailsGenerator

A details generator is a callback interface that Grid calls to create the Vaadin Component that is used for showing the details for a specific row. In this example, we create a layout that contains a label, an image and a button that all use data from the row.

Java

  1. grid.setDetailsGenerator(new DetailsGenerator() {
  2. @Override
  3. public Component getDetails(RowReference rowReference) {
  4. // Find the bean to generate details for
  5. final GridExampleBean bean = (GridExampleBean) rowReference.getItemId();
  6. // A basic label with bean data
  7. Label label = new Label("Extra data for " + bean.getName());
  8. // An image with extra details about the bean
  9. Image image = new Image();
  10. image.setWidth("300px");
  11. image.setHeight("150px");
  12. image.setSource(new ExternalResource("http://dummyimage.com/300x150/000/fff&text=" + bean.getCount()));
  13. // A button just for the sake of the example
  14. Button button = new Button("Click me", new Button.ClickListener() {
  15. @Override
  16. public void buttonClick(ClickEvent event) {
  17. Notification.show("Button clicked for " + bean.getName());
  18. }
  19. });
  20. // Wrap up all the parts into a vertical layout
  21. VerticalLayout layout = new VerticalLayout(label, image, button);
  22. layout.setSpacing(true);
  23. layout.setMargin(true);
  24. return layout;
  25. }
  26. });

Opening the details for a row

Since there are multiple different UI patterns for how details should be opened (e.g. clicking a button in a cell or double clicking anywhere on the row), Grid does not have any action enabled by default. You can instead implement your own listener that takes care of showing and hiding the details for the rows. One easy way of doing this is to add an item click listener that toggles the status whenever a row is double clicked.

Java

  1. grid.addItemClickListener(new ItemClickListener() {
  2. @Override
  3. public void itemClick(ItemClickEvent event) {
  4. if (event.isDoubleClick()) {
  5. Object itemId = event.getItemId();
  6. grid.setDetailsVisible(itemId, !grid.isDetailsVisible(itemId));
  7. }
  8. }
  9. });

Full example

Putting all these pieces together, we end up with this class that uses the same data as in the Using Grid with a Container example.

Java

  1. import com.vaadin.event.ItemClickEvent;
  2. import com.vaadin.event.ItemClickEvent.ItemClickListener;
  3. import com.vaadin.server.ExternalResource;
  4. import com.vaadin.server.VaadinRequest;
  5. import com.vaadin.ui.Button;
  6. import com.vaadin.ui.Button.ClickEvent;
  7. import com.vaadin.ui.Component;
  8. import com.vaadin.ui.Grid;
  9. import com.vaadin.ui.Grid.DetailsGenerator;
  10. import com.vaadin.ui.Grid.RowReference;
  11. import com.vaadin.ui.Image;
  12. import com.vaadin.ui.Label;
  13. import com.vaadin.ui.Notification;
  14. import com.vaadin.ui.UI;
  15. import com.vaadin.ui.VerticalLayout;
  16. public class ShowingExtraDataForRows extends UI {
  17. @Override
  18. protected void init(VaadinRequest request) {
  19. final Grid grid = new Grid();
  20. grid.setContainerDataSource(GridExampleHelper.createContainer());
  21. grid.setDetailsGenerator(new DetailsGenerator() {
  22. @Override
  23. public Component getDetails(RowReference rowReference) {
  24. // Find the bean to generate details for
  25. final GridExampleBean bean = (GridExampleBean) rowReference.getItemId();
  26. // A basic label with bean data
  27. Label label = new Label("Extra data for " + bean.getName());
  28. // An image with extra details about the bean
  29. Image image = new Image();
  30. image.setWidth("300px");
  31. image.setHeight("150px");
  32. image.setSource(new ExternalResource("http://dummyimage.com/300x150/000/fff&text=" + bean.getCount()));
  33. // A button just for the sake of the example
  34. Button button = new Button("Click me", new Button.ClickListener() {
  35. @Override
  36. public void buttonClick(ClickEvent event) {
  37. Notification.show("Button clicked for " + bean.getName());
  38. }
  39. });
  40. // Wrap up all the parts into a vertical layout
  41. VerticalLayout layout = new VerticalLayout(label, image, button);
  42. layout.setSpacing(true);
  43. layout.setMargin(true);
  44. return layout;
  45. }
  46. });
  47. grid.addItemClickListener(new ItemClickListener() {
  48. @Override
  49. public void itemClick(ItemClickEvent event) {
  50. if (event.isDoubleClick()) {
  51. Object itemId = event.getItemId();
  52. grid.setDetailsVisible(itemId, !grid.isDetailsVisible(itemId));
  53. }
  54. }
  55. });
  56. setContent(grid);
  57. }
  58. }