События Screen

В данном разделе описаны события жизненного цикла экрана, которые могут обрабатываться в контроллерах. Обратите внимание, что события не отвечают за сохранение настроек компонента; это берет на себя ScreenSettingsFacet.

InitEvent

InitEvent посылается, когда контроллер экрана и все его декларативно заданные компоненты созданы, а инжекция зависимостей завершена. Вложенные фрагменты на этом этапе еще не инициализированы. Некоторые визуальные компоненты инициализированы не полностью: например, кнопки ещё не связаны с действиями.

@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 посылается, когда контроллер экрана и все его декларативно заданные компоненты созданы, инжекция зависимостей завершена, и все компоненты завершили свою внутреннюю процедуру инициализации. Вложенные фрагменты (при наличии) опубликовали свои события InitEvent и AfterInitEvent. В слушателе этого события можно создавать визуальные компоненты и компоненты данных, а также выполнить дополнительную инициализацию, если она зависит от инициализации вложенных фрагментов.

InitEntityEvent

InitEntityEvent посылается в экранах, унаследованных от StandardEditor и MasterDetailScreen, перед тем, как новый экземпляр сущности будет установлен для контейнера редактируемой сущности.

Используйте слушатель этого события, чтобы инициализировать значения по умолчанию для новых экземпляров сущностей, например:

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

BeforeShowEvent

BeforeShowEvent посылается непосредственно перед тем, как экран будет отображен, например, если он еще не добавлен к интерфейсу приложения. Ограничения безопасности уже применены к компонентам UI. В слушателе этого события можно загружать данные, проверять разрешения безопасности и изменять компоненты интерфейса. Например:

@Autowired
private CollectionLoader<Order> ordersDl;

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

AfterShowEvent

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

@Autowired
private Notifications notifications;

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

BeforeCommitChangesEvent

BeforeCommitChangesEvent посылается в экранах, унаследованных от StandardEditor и MasterDetailScreen, перед сохранением измененных данных методом commitChanges(). В слушателе этого события можно проверить некоторые условия и прервать или продолжить операцию сохранения с помощью методов preventCommit() и resume() объекта события.

Рассмотрим некоторые варианты использования.

  • Прервать операцию сохранения с выводом уведомления:

    @Autowired
    private Notifications notifications;
    
    @Subscribe
    public void onBeforeCommitChanges(BeforeCommitChangesEvent event) {
        if (getEditedEntity().getAmount() == null) {
            notifications.create().withCaption("Enter amount").show();
            event.preventCommit();
        }
    }
  • Прервать операцию сохранения, показать диалог и продолжить после подтверждения пользователем:

    @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();
        }
    }
  • Прервать операцию сохранения, показать диалог и повторить commitChanges() после подтверждения пользователем:

    @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 посылается в экранах, унаследованных от StandardEditor и MasterDetailScreen, после сохранения измененных данных методом commitChanges(). Пример использования:

@Autowired
private Notifications notifications;

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

BeforeCloseEvent

BeforeCloseEvent посылается непосредственно перед закрытием экрана с помощью метода close(CloseAction). На этом этапе экран еще отображается и полностью функционален. В слушателе этого события можно проверить некоторые условия и предотвратить закрытие экрана, используя метод события preventWindowClose(), например:

@Autowired
private CheckBox checkBox;

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

Одноименный метод также определен в интерфейсе Window. Он вызывается перед тем, как экран будет закрыт неким внешним (относительно контроллера) действием, таким как нажатие кнопки во вкладке окна или клавиши Escape на клавиатуре. Способ, которым экран был закрыт, можно получить с помощью метода getCloseOrigin(), который возвращает значение в виде объекта, реализующего интерфейс CloseOrigin. Реализация этого интерфейса по умолчанию CloseOriginType включает в себя три значения:

  • BREADCRUMBS - экран закрыт по клику на цепочке ссылок (breadcrumbs).

  • CLOSE_BUTTON - экран закрыт по нажатию на кнопку закрытия в заголовке окна, на кнопку закрытия вкладки или через действия в контекстном меню: Close, Close All, Close Others.

  • SHORTCUT - экран закрыт нажатием горячих клавиш, определенных в свойстве приложения jmix.ui.screen.close-shortcut.

Вы можете подписаться на событие Window.BeforeCloseEvent, указав Target.FRAME в аннотации @Subscribe:

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

AfterCloseEvent

AfterCloseEvent посылается после того, как экран будет закрыт методом close(CloseAction), и после события Screen.AfterDetachEvent. Слушатель этого события можно использовать для вывода уведомлений или диалоговых окон после закрытия экрана, например:

@Autowired
private Notifications notifications;

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

AfterDetachEvent

AfterDetachEvent посылается после того, как экран удаляется из интерфейса приложения после закрытия экрана пользователем или выхода пользователя из системы. Слушатель этого события можно использовать для освобождения ресурсов, захваченных экраном. Обратите внимание, что при истечении HTTP-сессии это событие не публикуется.

UrlParamsChangedEvent

UrlParamsChangedEvent посылается, когда изменяются параметры URL браузера, соответствующие данному экрану. Событие вызывается перед отображением экрана, что позволяет произвести некоторую подготовительную работу. В слушателе этого события можно загружать данные или изменять состояние элементов управления в экране в соответствии с новыми параметрами:

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