Screen Events

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

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.

@Autowired
private UiComponents uiComponents;

@Subscribe
public void onInit(InitEvent event) {
    Label<String> label = uiComponents.create(Label.TYPE_STRING);
    label.setValue("Orders list");
    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.

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

@Subscribe
public void onInitEntity(InitEntityEvent<Order> event) {
    event.getEntity().setRating(10);
}

BeforeShowEvent

BeforeShowEvent is sent right before the screen is shown, for example, 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. In this event listener, you can load data, check permissions and modify UI components. For example:

@Autowired
private CollectionLoader<Order> ordersDl;

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

AfterShowEvent

AfterShowEvent is sent right after the screen is shown, for example, 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:

@Autowired
private Notifications notifications;

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

  • Abort the save operation with a notification:

    @Autowired
    private Notifications notifications;
    
    @Subscribe
    public void onBeforeCommitChanges(BeforeCommitChangesEvent event) {
        if (getEditedEntity().getAmount() == null) {
            notifications.create().withCaption("Enter amount").show();
            event.preventCommit();
        }
    }
  • Abort saving, show a dialog and resume after confirmation by the user:

    @Autowired
    private Dialogs dialogs;
    
    @Subscribe
    public void onBeforeCommitChanges(BeforeCommitChangesEvent event) {
        if (getEditedEntity().getNum() == null) {
            dialogs.createOptionDialog()
                    .withCaption("Confirmation")
                    .withMessage("Number is empty. Do you want to commit?")
                    .withActions(
                            new DialogAction(DialogAction.Type.OK).withHandler(e -> {
                                event.resume();
                            }),
                            new DialogAction(DialogAction.Type.CANCEL)
                    )
                    .show();
            event.preventCommit();
        }
    }
  • Abort saving, show a dialog and retry commitChanges() after confirmation by the user:

    @Autowired
    private Dialogs dialogs;
    
    @Subscribe
    public void onBeforeCommitChanges(BeforeCommitChangesEvent event) {
        if (getEditedEntity().getNum() == null) {
            dialogs.createOptionDialog()
                    .withCaption("Confirmation")
                    .withMessage("Number is empty. Do you want to set default?")
                    .withActions(
                            new DialogAction(DialogAction.Type.OK).withHandler(e -> {
                                getEditedEntity().setNum(DEFAULT_NUM);
                                event.resume(commitChanges());
                            }),
                            new DialogAction(DialogAction.Type.CANCEL)
                    )
                    .show();
            event.preventCommit();
        }
    }

AfterCommitChangesEvent

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

@Autowired
private Notifications notifications;

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

@Autowired
private CheckBox checkBox;

@Subscribe
protected void onBeforeClose(BeforeCloseEvent event) {
    if (!checkBox.isChecked()) {
        notifications.create().withCaption("Select checkbox").show();
        event.preventWindowClose();
    }
}

The Window interface has also an event with the same name. 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 Escape 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 jmix.ui.screen.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:

@Autowired
private Notifications notifications;

@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();
    notifications.create().withCaption("Params").show();
    // handle new params
}