Не показывать контекстное меню для определенных строк в DataGrid

Подскажите, пожалуйста, как в DataGrid для определенных строк не показывать контекстное меню. К сожалению у DataGrid.ContextClickEvent нет метода preventDefault который бы меня спас(((
Пробовал в addContextClickListener вызывать setContextMenuEnabled(false), но данный вариант действует только для всех последующих вызовов контекстного меню. Также пробовал запрещать вызов контекстного меню в addSelectionListener, но он тоже очевидно вызывается после вызова меню.

Добрый день.

Чтобы иметь возможность предотвращать открытие контекстного меню для некоторых строк, Вам необходимо расширить компонент DataGrid и задать для него свою реализацию CubaGridContextMenu.

Для этого, вам необходимо создать класс наследник WebDataGrid, который переопределит метод initContextMenu(), и класс наследник CubaGridContextMenu, который переопределит onContextClick в котором можно добавить beforeContextMenuOpenHandler. Например:

import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.web.gui.components.WebDataGrid;
import com.haulmont.cuba.web.widgets.grid.CubaGridContextMenu;
import com.vaadin.shared.ui.grid.GridConstants;
import com.vaadin.ui.Grid;

import java.util.function.Function;

public class WebDataGridExt<E extends Entity> extends WebDataGrid<E> {

    private Function<E, Boolean> beforeContextMenuOpenHandler;

    @Override
    protected void initContextMenu() {
        contextMenu = new CubaGridContextMenuExt<>(component);

        contextMenu.addGridBodyContextMenuListener(event -> {
            if (!component.getSelectedItems().contains(event.getItem())) {
                // In the multi select model 'setSelected' adds item to selected set,
                // but, in case of context click, we want to have a single selected item,
                // if it isn't in a set of already selected items
                if (isMultiSelect()) {
                    component.deselectAll();
                }
                setSelected(event.getItem());
            }
        });
    }

    public void setBeforeContextMenuOpenHandler(Function<E, Boolean> beforeContextMenuOpenHandler) {
        this.beforeContextMenuOpenHandler = beforeContextMenuOpenHandler;
    }

    public class CubaGridContextMenuExt<T> extends CubaGridContextMenu<T> {

        public CubaGridContextMenuExt(Grid<T> parentComponent) {
            super(parentComponent);
        }

        @Override
        protected void onContextClick(com.vaadin.event.ContextClickEvent event) {
            if (!isEnabled()) {
                return;
            }

            // prevent opening context menu in non BODY sections
            if (event instanceof Grid.GridContextClickEvent) {
                Grid.GridContextClickEvent gridEvent = (Grid.GridContextClickEvent) event;
                if (!gridEvent.getSection().equals(GridConstants.Section.BODY)) {
                    return;
                }

                fireEvent(new ContextMenuOpenListener.ContextMenuOpenEvent(CubaGridContextMenuExt.this, event));

                if (beforeContextMenuOpenHandler != null) {
                    if (!beforeContextMenuOpenHandler.apply((E) ((Grid.GridContextClickEvent) event).getItem())) {
                        return;
                    }
                }

                open(event.getClientX(), event.getClientY());
            }
        }
    }
}

Чтобы компонент мог использоваться во всем приложении, необходимо зарегистрировать его, создав файл ui-component.xml в корневом пакете web модуля и зарегистрировав его в web-app.properties:

ui-component.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<components xmlns="http://schemas.haulmont.com/cuba/components.xsd">
    <component>
        <name>dataGrid</name>
        <class>com.company.sales.web.gui.components.WebDataGridExt</class>
    </component>
</components>

web-app.properties

cuba.web.componentsConfig = +com/company/sales/ui-component.xml

После чего, созданный компонент можно использовать в экранах:

@Inject
private DataGrid<Product> dataGrid;

@Subscribe
private void onInit(InitEvent event) {
    ((WebDataGridExt<Product>) dataGrid).setBeforeContextMenuOpenHandler(item -> false);
}

Полный код можно найти в демо приложении demo.zip (116,0 КБ).

3 симпатии