3.5.1.1.3. Screen Events

This section describes the screen lifecycle events that can be handled in controllers.

See Decouple Business Logic with Application Events guide to learn how to use events on the UI layer.



InitEvent

InitEvent is sent when the screen controller and all its declaratively defined components are created, and dependency injection is completed. Nested fragments are not initialized yet. Some visual components are not fully initialized, for example buttons are not linked with actions.

@Subscribe
protected void onInit(InitEvent event) {
    Label<String> label = uiComponents.create(Label.TYPE_STRING);
    label.setValue("Hello World");
    getWindow().add(label);
}
AfterInitEvent

AfterInitEvent is sent when the screen controller and all its declaratively defined components are created, dependency injection is completed, and all components have completed their internal initialization procedures. Nested screen fragments (if any) have sent their InitEvent and AfterInitEvent. In this event listener, you can create visual and data components and perform additional initialization if it depends on initialized nested fragments.

InitEntityEvent

InitEntityEvent is sent in screens inherited from StandardEditor and MasterDetailScreen before the new entity instance is set to edited entity container.

See also Initial Entity Values guide to learn how to use InitEntityEvent listeners.

Use this event listener to initialize default values in the new entity instance, for example:

@Subscribe
protected void onInitEntity(InitEntityEvent<Foo> event) {
    event.getEntity().setStatus(Status.ACTIVE);
}
BeforeShowEvent

BeforeShowEvent is sent right before the screen is shown, i.e. it is not added to the application UI yet. Security restrictions are applied to UI components. Saved component settings are not yet applied to UI components. Data is not loaded yet for screens annotated with @LoadDataBeforeShow. In this event listener, you can load data, check permissions and modify UI components. For example:

@Subscribe
protected void onBeforeShow(BeforeShowEvent event) {
    customersDl.load();
}
AfterShowEvent

AfterShowEvent is sent right after the screen is shown, i.e. when it is added to the application UI. Saved component settings are applied to UI components. In this event listener, you can show notifications, dialogs or other screens. For example:

@Subscribe
protected void onAfterShow(AfterShowEvent event) {
    notifications.create().withCaption("Just opened").show();
}
BeforeCommitChangesEvent

BeforeCommitChangesEvent is sent in screens inherited from StandardEditor and MasterDetailScreen before saving of changed data by the commitChanges() method. In this event listener, you can check any conditions, interact with the user and abort or resume the save operation using the preventCommit() and resume() methods of the event object.

Let’s consider some use cases.

  1. Abort the save operation with a notification:

    @Subscribe
    public void onBeforeCommitChanges(BeforeCommitChangesEvent event) {
        if (getEditedEntity().getStatus() == null) {
            notifications.create().withCaption("Enter status!").show();
            event.preventCommit();
        }
    }
  2. Abort saving, show a dialog and resume after confirmation by the user:

    @Subscribe
    public void onBeforeCommitChanges(BeforeCommitChangesEvent event) {
        if (getEditedEntity().getStatus() == null) {
            dialogs.createOptionDialog()
                    .withCaption("Confirmation")
                    .withMessage("Status is empty. Do you really want to commit?")
                    .withActions(
                            new DialogAction(DialogAction.Type.OK).withHandler(e -> {
                                // resume with default behavior
                                event.resume();
                            }),
                            new DialogAction(DialogAction.Type.CANCEL)
                    )
                    .show();
            // abort
            event.preventCommit();
        }
    }
  3. Abort saving, show a dialog and retry commitChanges() after confirmation by the user:

    @Subscribe
    public void onBeforeCommitChanges(BeforeCommitChangesEvent event) {
        if (getEditedEntity().getStatus() == null) {
            dialogs.createOptionDialog()
                    .withCaption("Confirmation")
                    .withMessage("Status is empty. Do you want to use default?")
                    .withActions(
                            new DialogAction(DialogAction.Type.OK).withHandler(e -> {
                                getEditedEntity().setStatus(getDefaultStatus());
                                // retry commit and resume action
                                event.resume(commitChanges());
                            }),
                            new DialogAction(DialogAction.Type.CANCEL)
                    )
                    .show();
            // abort
            event.preventCommit();
        }
    }
AfterCommitChangesEvent

AfterCommitChangesEvent is sent in screens inherited from StandardEditor and MasterDetailScreen after saving of changed data by the commitChanges() method. Usage example:

@Subscribe
public void onAfterCommitChanges(AfterCommitChangesEvent event) {
    notifications.create()
            .withCaption("Saved!")
            .show();
}
BeforeCloseEvent

BeforeCloseEvent is sent right before the screen is closed by its close(CloseAction) method. The screen is still displayed and fully functional. Component settings are not saved yet. In this event listener, you can check any conditions and prevent screen closing using the preventWindowClose() method of the event, for example:

@Subscribe
protected void onBeforeClose(BeforeCloseEvent event) {
    if (Strings.isNullOrEmpty(textField.getValue())) {
        notifications.create().withCaption("Input required").show();
        event.preventWindowClose();
    }
}

There is also an event with the same name but defined in the Window interface. It is sent before the screen is closed by an external (relative to the controller) action, like clicking on the button in the window tab or by pressing the Esc key. The way the window is closed can be obtained using the getCloseOrigin() method which returns a value implementing the CloseOrigin interface. Its default implementation CloseOriginType has three values:

  • BREADCRUMBS - the screen is closed by clicking on the breadcrumbs link.

  • CLOSE_BUTTON - the screen is closed by the close button in the window header or by the window tab close button or context menu actions: Close, Close All, Close Others.

  • SHORTCUT - the screen is closed by the keyboard shortcut defined in the cuba.gui.closeShortcut application property.

You can subscribe to Window.BeforeCloseEvent by specifying Target.FRAME in the @Subscribe annotation:

@Subscribe(target = Target.FRAME)
protected void onBeforeClose(Window.BeforeCloseEvent event) {
    if (event.getCloseOrigin() == CloseOriginType.BREADCRUMBS) {
        event.preventWindowClose();
    }
}
AfterCloseEvent

AfterCloseEvent is sent after the screen is closed by its close(CloseAction) method and after Screen.AfterDetachEvent. Component settings are saved. In this event listener, you can show notifications or dialogs after closing the screen, for example:

@Subscribe
protected void onAfterClose(AfterCloseEvent event) {
    notifications.create().withCaption("Just closed").show();
}
AfterDetachEvent

AfterDetachEvent is sent after the screen is removed from the application UI when it is closed by the user or when the user logs out. This event listener can be used for releasing resources acquired by the screen. Note that this event is not sent on HTTP session expiration.

UrlParamsChangedEvent

UrlParamsChangedEvent is sent when browser URL parameters corresponding to opened screen are changed. It is fired before the screen is shown, which enables to do some preparatory work. In this event listener, you can load some data or change screen controls state depending on new parameters:

@Subscribe
protected void onUrlParamsChanged(UrlParamsChangedEvent event) {
    Map<String, String> params = event.getParams();
    // handle new params
}