Search code examples
javadatagridright-clickvaadin8

How to use Vaadin Action Framework in Grid of Vaadin 8


Using the Table class of Vaadin one could add an action handler to a table. For example in previous Vaadin versions the following 2 options could be shown to the screen when a user right-click inside the table area:

Table aTable=new Table();
aTable.addActionHandler(new Action.Handler(){

public Action[] getActions(Object target, Object sender)
  {                           
  //example, that shows 2 options
  return new Action[] {new Action("Option 1"), new Action("Option 2")};

public void handleAction(Action action, Object sender, Object target)
  {//just prints action name for this example
   System.out.println("Action:"+action);
   }
});     

Action.Handler exist in Vaadin 8 however it is not possible to add an Action.Handler to a Grid in Vaadin 8, nor have I found any other way to create a context menu.

What would be the way to use the Action Framework in a Grid? Does Grid have any other method for creating a context menu? In other words, how would the example above be written.

Existing articles and answers (e.g. Vaadin Grid vs Table) do not cover the topic above, and it is not documented in Vaadin docs (https://vaadin.com/docs/-/part/framework/components/components-grid.html).


Solution

  • You can use the vaadin-context-menu add-on introduced since Vaadin 7.6 (online demo and github source). Theoretically it can support any component, but for the grid we'll use the dedicated GridContextMenu (remember to recompile your widgetset).

    Dependency:

    <dependency>
       <groupId>com.vaadin</groupId>
       <artifactId>vaadin-context-menu</artifactId>
       <version>2.0.0</version>
    </dependency>
    

    Implementation:

    import com.vaadin.contextmenu.GridContextMenu;
    import com.vaadin.icons.VaadinIcons;
    import com.vaadin.ui.Grid;
    import com.vaadin.ui.Notification;
    import com.vaadin.ui.UI;
    import com.vaadin.ui.VerticalLayout;
    
    public class MyUi extends UI {
        @Override
        protected void init(VaadinRequest request) {
            // basic grid setup
            Grid<Person> grid = new Grid<>(Person.class);
            grid.getColumns().forEach(column -> column.setHidable(true).setSortable(true));
            grid.setItems(
                    new Person("Darth", "Vader"),
                    new Person("Luke", "Skywalkaer"),
                    new Person("Java", "De-Hut")
            );
    
            // grid context menu setup
            Random random = new Random();
            GridContextMenu<Person> contextMenu = new GridContextMenu<>(grid);
            // handle header right-click
            contextMenu.addGridHeaderContextMenuListener(event -> {
                contextMenu.removeItems();
                contextMenu.addItem("Hide", VaadinIcons.EYE_SLASH, selectedMenuItem -> {
                    event.getColumn().setHidden(true);
                });
                contextMenu.addItem("Sort", VaadinIcons.LIST_OL, selectedMenuItem -> {
                    grid.sort(event.getColumn().getId(), SortDirection.values()[random.nextInt(2)]);
                });
            });
            // handle item right-click
            contextMenu.addGridBodyContextMenuListener(event -> {
                contextMenu.removeItems();
                if (event.getItem() != null) {
                    grid.select((Person) event.getItem());
                    contextMenu.addItem("Info", VaadinIcons.INFO, selectedMenuItem -> {
                        Notification.show("Right-clicked item " + event.getItem());
                    });
                }
            });
    
            // set UI content
            VerticalLayout content = new VerticalLayout();
            content.setSizeFull();
            content.addComponents(grid);
            setContent(content);
        }
    
        // basic bean
        public static class Person {
            private String firstName;
            private String lastName;
    
            public Person(String firstName, String lastName) {
                this.firstName = firstName;
                this.lastName = lastName;
            }
    
            public String getFirstName() {
                return firstName;
            }
    
            public void setFirstName(String firstName) {
                this.firstName = firstName;
            }
    
            public String getLastName() {
                return lastName;
            }
    
            public void setLastName(String lastName) {
                this.lastName = lastName;
            }
    
            @Override
            public String toString() {
                return "Person{" +
                        "firstName='" + firstName + '\'' +
                        ", lastName='" + lastName + '\'' +
                        '}';
            }
        }
    }
    

    Result:

    grid context menu