3.5.5.2.13. ViewAction

ViewAction is a list action designed to view and edit entity instances. It opens the edit screen in the same way as EditAction, but it makes all fields non-editable and disables actions implementing interface Action.DisabledWhenScreenReadOnly. If you want to allow users to switch the screen to the editable mode, add a button and link it with the predefined enableEditing action:

<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>

You can redefine the enableEditing action caption in main message pack using the actions.EnableEditing key, or right in the screen by specifying the caption attribute to the corresponding button.

ViewAction is implemented by com.haulmont.cuba.gui.actions.list.ViewAction class and should be defined in XML using type="view" action’s attribute. You can configure common action parameters using XML attributes of the action element, see Declarative Actions for details. Below we describe parameters specific to the ViewAction class.

The following parameters can be set both in XML and in Java:

  • openMode - the editor screen opening mode as a value of the OpenMode enum: NEW_TAB, DIALOG, etc. By default, ViewAction opens the editor in THIS_TAB mode.

  • screenId - string id of the editor screen to use. By default, ViewAction uses either a screen, annotated with @PrimaryEditorScreen, or having identifier in the format of <entity_name>.edit, e.g. demo_Customer.edit.

  • screenClass - Java class of the editor screen controller to use. It has higher priority than screenId.

For example, if you want to open a specific editor screen as a dialog, you can configure the action in XML:

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

Alternatively, you can inject the action into the screen controller and configure it using setters:

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

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

Now let’s consider parameters that can be configured only in Java code. In order to generate correctly annotated method stubs for these parameters, use Handlers tab of the Component Inspector tool window in Studio.

  • screenOptionsSupplier - a handler that returns ScreenOptions object to be passed to the opened editor screen. For example:

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

    The returned ScreenOptions object will be available in the InitEvent of the opened screen.

  • screenConfigurer - a handler that accepts the editor screen and can initialize it before opening. For example:

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

    Note that screen configurer comes into play when the screen is already initialized but not yet shown, i.e. after its InitEvent and AfterInitEvent and before BeforeShowEvent are sent.

  • afterCommitHandler - a handler that is invoked after the edited entity instance is committed in the editor screen, if the user switched the screen to editable mode using enableEditing action mentioned above. The handler method accepts the updated entity. For example:

    @Install(to = "customersTable.view", subject = "afterCommitHandler")
    protected void customersTableViewAfterCommitHandler(Customer entity) {
        System.out.println("Updated " + entity);
    }
  • afterCloseHandler - a handler that is invoked after the editor screen is closed. AfterCloseEvent is passed to the handler. For example:

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

If you want to perform some checks or interact with the user before the action is executed, subscribe to the action’s ActionPerformedEvent and invoke execute() method of the action when needed. The action will be invoked with all parameters that you defined for it. In the example below, we show a confirmation dialog before executing the action:

@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();
}

You can also subscribe to ActionPerformedEvent and instead of invoking the action’s execute() method, use ScreenBuilders API directly to open the edit screen. In this case, you are ignoring all specific action parameters and behavior and using only its common parameters like caption, icon, etc. For example:

@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();
}