3.5.5.2.13. ViewAction

ViewAction - действие с коллекцией, предназначенное для просмотра и редактирования экземпляров сущности. Оно открывает экран редактирования таким же образом, как EditAction, но делает все поля ввода нередактируемыми и запрещает действия, реализующие интерфейс Action.DisabledWhenScreenReadOnly. Если необходимо дать пользователю возможность переключить экран в режим редактирования, добавьте в экран кнопку и свяжите ее с предопределенным действием enableEditing:

<hbox id="editActions" spacing="true">
    <button action="windowCommitAndClose"/>
    <button action="windowClose"/>
    <button action="enableEditing"/> <!-- this button is shown only when the screen is in read-only mode -->
</hbox>

Заголовок действия enableEditing можно переопределить в главном пакете сообщений, используя ключ actions.EnableEditing, или непосредственно в экране путем указания атрибута caption у соответствующей кнопки.

Действие реализовано классом com.haulmont.cuba.gui.actions.list.ViewAction и объявляется в XML с помощью атрибута type="view". Общие свойства действий можно конфигурировать с помощью атрибутов элемента action, подробнее см. раздел Декларативное создание действий. Ниже рассматриваются параметры, специфичные для класса ViewAction.

Следующие параметры можно установить и в XML и в Java:

  • openMode - режим открытия экрана редактирования, задаваемый значением перечисления OpenMode: NEW_TAB, DIALOG, и т.д. По умолчанию экран открывается в режиме THIS_TAB.

  • screenId - строковый идентификатор экрана редактирования. По умолчанию используется экран, аннотированный @PrimaryEditorScreen, или имеющий идентификатор вида <entity_name>.edit, например demo_Customer.edit.

  • screenClass - класс Java экрана редактирования. Данный параметр имеет более высокий приоритет, чем screenId.

Например, если необходимо открыть определенный экран редактирования в режиме диалога, действие можно сконфигурировать в XML следующим образом:

<action id="view" type="view">
    <properties>
        <property name="openMode" value="DIALOG"/>
        <property name="screenClass" value="com.company.sales.web.customer.CustomerEdit"/>
    </properties>
</action>

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

@Named("customersTable.view")
private ViewAction customersTableView;

@Subscribe
public void onInit(InitEvent event) {
    customersTableView.setOpenMode(OpenMode.DIALOG);
    customersTableView.setScreenClass(CustomerEdit.class);
}

Далее рассматриваются параметры, которые можно сконфигурировать только программно в Java. Для генерации корректно аннотированных методов для этих параметров используйте закладку Handlers окна инструментов Component Inspector в Studio.

  • screenOptionsSupplier - обработчик, возвращающий объект ScreenOptions для передачи в открываемый экран редактирования. Например:

    @Install(to = "customersTable.view", subject = "screenOptionsSupplier")
    protected ScreenOptions customersTableViewScreenOptionsSupplier() {
        return new MapScreenOptions(ParamsMap.of("someParameter", 10));
    }

    Возвращаемый объект ScreenOptions будет доступен в InitEvent открываемого экрана.

  • screenConfigurer - обработчик, принимающий экран редактирования для его конфигурирования перед открытием. Например:

    @Install(to = "customersTable.view", subject = "screenConfigurer")
    protected void customersTableViewScreenConfigurer(Screen editorScreen) {
        ((CustomerEdit) editorScreen).setSomeParameter(10);
    }

    Конфигуратор экрана вступает в действие, когда экран уже инициализирован, но еще не показан, то есть после InitEvent и AfterInitEvent, и до BeforeShowEvent.

  • afterCommitHandler - обработчик, вызываемый после коммита редактируемого экземпляра сущности в экране редактирования, если пользователь переключил экран в режим редактирования используя действие enableEditing, упомянутое выше. Принимает сохраненный в БД экземпляр сущности. Например:

    @Install(to = "customersTable.view", subject = "afterCommitHandler")
    protected void customersTableViewAfterCommitHandler(Customer entity) {
        System.out.println("Updated " + entity);
    }
  • afterCloseHandler - обработчик, вызываемый после закрытия экрана редактирования. Принимает AfterCloseEvent. Например:

    @Install(to = "customersTable.view", subject = "afterCloseHandler")
    protected void customersTableViewAfterCloseHandler(AfterCloseEvent event) {
        if (event.closedWith(StandardOutcome.COMMIT)) {
            System.out.println("Enabled editing and then committed");
        }
    }

Для того, чтобы произвести какие-либо проверки, или взаимодействовать с пользователем перед выполнением действия, необходимо подписаться на событие ActionPerformedEvent действия и в нужный момент вызвать метод execute(). Действие будет вызвано со всеми параметрами, которые были для него заданы. В примере ниже перед выполнением действия отображается диалог подтверждения:

@Named("customersTable.view")
private ViewAction customersTableView;

@Subscribe("customersTable.view")
public void onCustomersTableView(Action.ActionPerformedEvent event) {
    dialogs.createOptionDialog()
            .withCaption("Please confirm")
            .withMessage("Do you really want to view the customer?")
            .withActions(
                    new DialogAction(DialogAction.Type.YES)
                            .withHandler(e -> customersTableView.execute()), // execute action
                    new DialogAction(DialogAction.Type.NO)
            )
            .show();
}

Можно также подписаться на ActionPerformedEvent, и вместо вызова метода execute() действия, использовать для открытия экрана редактирования ScreenBuilders API напрямую. По сути, в этом случае все специфичные параметры действия игнорируются, и действуют только общие параметры: caption, icon, и т.д. Например:

@Inject
private ScreenBuilders screenBuilders;

@Subscribe("customersTable.view")
public void onCustomersTableView(Action.ActionPerformedEvent event) {
    CustomerEdit customerEdit = screenBuilders.editor(customersTable)
            .withOpenMode(OpenMode.DIALOG)
            .withScreenClass(CustomerEdit.class)
            .withAfterCloseListener(afterScreenCloseEvent -> {
                if (afterScreenCloseEvent.closedWith(StandardOutcome.COMMIT)) {
                    Customer committedCustomer = (afterScreenCloseEvent.getScreen()).getEditedEntity();
                    System.out.println("Updated " + committedCustomer);
                }
            })
            .build();
    customerEdit.setReadOnly(true);
    customerEdit.show();
}