События экранов
Этот раздел описывает события жизненного цикла экранов, которые можно обрабатывать в контроллерах. Для получения общего представления о последовательности событий, см. диаграммы в конце раздела.
Для генерации обработчика события экрана в Jmix Studio, выберите корневой элемент В качестве альтернативы, выполните действие Generate Handler, доступное в верхней панели класса экрана и через меню Code → Generate (Alt+Insert / Cmd+N). |
InitEvent
InitEvent
— это первое событие в процессе открытия экрана. Экран и все его компоненты, определенные декларативно, созданы, инжекция зависимостей выполнена. Некоторые визуальные компоненты не полностью инициализированы, например, кнопки не связаны с действиями. В этом событии можно создавать и/или инициализировать визуальные компоненты и компоненты данных.
@ViewComponent
private JmixComboBox<String> timeZoneField;
@Subscribe
public void onInit(final InitEvent event) {
timeZoneField.setItems(List.of(TimeZone.getAvailableIDs()));
}
Событие отсылается только один раз после создания экрана. Это означает, что если навигация на экран происходит впервые, то событие отсылается. Однако, если навигация выполняется на экран, который уже открыт, например, при повторном клике на один и тот же элемент меню, событие не будет отослано снова, потому что экран уже создан. |
BeforeShowEvent
BeforeShowEvent
— это второе событие (после View.InitEvent
) в процессе открытия экрана. Все компоненты завершили внутреннюю процедуру инициализации. Загрузчики данных вызваны автоматически настроенным фасетом DataLoadCoordinator. Политики безопасности применены к UI-компонентам. В этом событии можно загружать данные, проверять разрешения и модифицировать UI-компоненты. Например:
@ViewComponent
private CollectionLoader<User> usersDl;
@Subscribe
public void onBeforeShow(final BeforeShowEvent event) {
usersDl.load();
}
Повторная навигация на экран, который уже открыт, приводит к отсылке Например, пользователь переходит на экран впервые, создается экземпляр экрана и отсылается
|
ReadyEvent
ReadyEvent
— это последнее событие (после View.BeforeShowEvent
) в процессе открытия экрана. В обработчике этого события можно выполнить окончательную конфигурацию экрана в соответствии с загруженными данными и показать уведомления или диалоги.
@Autowired
private Notifications notifications;
@Subscribe
public void onReady(final ReadyEvent event) {
notifications.show("Just opened");
}
Повторная навигация на экран, который уже открыт, приводит к отсылке Например, пользователь переходит на экран впервые, создается экземпляр экрана и отсылается
|
AttachEvent
AttachEvent
отсылается после того, как экран прикреплен к UI.
@Subscribe
public void onAttachEvent(final AttachEvent event) {
log.debug("View is attached");
}
Это событие отсылается Vaadin, поскольку экран также является UI-компонентом. |
BeforeCloseEvent
BeforeCloseEvent
- это первое событие в процессе закрытия экрана. Экран все еще отображается и полностью функционален. В обработчике этого события вы можете проверить любые условия и предотвратить закрытие с помощью метода preventClose()
события.
@Subscribe
public void onBeforeClose(BeforeCloseEvent event) {
if (!isLicenseAgreementAccepted()) {
CloseAction action = event.getCloseAction();
if (action instanceof NavigateCloseAction navigateCloseAction) {
BeforeLeaveEvent beforeLeaveEvent = navigateCloseAction.getBeforeLeaveEvent();
beforeLeaveEvent.postpone();
}
event.preventClose();
}
}
Если вы предотвращаете закрытие экрана, в случае навигации вам нужно ее отложить. Проверьте тип действия, и если это NavigateCloseAction , получите BeforeLeaveEvent Vaadin и вызовите его метод postpone() .
|
AfterCloseEvent
AfterCloseEvent
- это второе событие (после View.BeforeCloseEvent
) в процессе закрытия экрана. В обработчике этого события вы можете показывать уведомления или диалоги после закрытия экрана, например:
@Autowired
private Notifications notifications;
@Subscribe
public void onAfterClose(final AfterCloseEvent event) {
notifications.show("View is closed");
}
DetachEvent
DetachEvent
срабатывает перед отсоединением экрана от пользовательского интерфейса. Этот обработчик событий можно использовать для освобождения ресурсов, захваченных экраном.
@Subscribe
public void onDetachEvent(final DetachEvent event) {
log.debug("View is detached");
}
Это событие генерируется Vaadin, поскольку экран также является UI-компонентом. |
QueryParametersChangeEvent
QueryParametersChangeEvent
информирует, с какими параметрами запроса был открыт экран. Он отсылается после InitEvent
, если экран был открыт навигацией.
@ViewComponent
private Span messageLabel;
public void setMessage(String message) {
messageLabel.setText(message);
}
@Subscribe
public void onQueryParametersChange(final QueryParametersChangeEvent event) {
event.getQueryParameters()
.getSingleParameter("message")
.ifPresent(this::setMessage);
}
InitEntityEvent
InitEntityEvent
отсылается в экранах, унаследованных от StandardDetailView, перед установкой нового экземпляра сущности в контейнер редактируемой сущности.
Используйте обработчик этого события для инициализации значений в новом экземпляре сущности, например:
@Subscribe
public void onInitEntity(final InitEntityEvent<User> event) {
User user = event.getEntity();
user.setOnboardingStatus(OnboardingStatus.NOT_STARTED);
}
ValidationEvent
ValidationEvent
отсылается в экранах, унаследованных от StandardDetailView
, когда экран проходит валидацию при сохранении DataContext экрана. Используйте обработчик этого события для выполнения дополнительной проверки экрана.
@Subscribe
public void onValidation(final ValidationEvent event) {
if (entityStates.isNew(getEditedEntity())
&& !Objects.equals(passwordField.getValue(), confirmPasswordField.getValue())) {
event.getErrors().add("Passwords do not match");
}
}
BeforeSaveEvent
BeforeSaveEvent
отсылается в экранах, унаследованных от StandardDetailView
, перед сохранением DataContext
экрана. Используйте обработчик этого события для предотвращения сохранения, изменения значений атрибутов сущности перед сохранением и/или взаимодействия с пользователем перед сохранением.
@ViewComponent
private JmixPasswordField passwordField;
@ViewComponent
private JmixPasswordField confirmPasswordField;
@Autowired
private EntityStates entityStates;
@Autowired
private PasswordEncoder passwordEncoder;
@Subscribe
public void onBeforeSave(final BeforeSaveEvent event) {
if (entityStates.isNew(getEditedEntity())) {
if (!Objects.equals(passwordField.getValue(), confirmPasswordField.getValue())) {
notifications.create("Passwords do not match")
.withType(Notifications.Type.WARNING)
.show();
event.preventSave(); (1)
}
getEditedEntity().setPassword(passwordEncoder.encode(passwordField.getValue())); (2)
}
}
1 | Прервать процесс сохранения, если пароли не совпадают. |
2 | Установить закодированный пароль в сущность. |
AfterSaveEvent
AfterSaveEvent
отсылается в экранах, унаследованных от StandardDetailView
, после сохранения DataContext
экрана. Используйте обработчик этого события для уведомления пользователей после сохранения, например:
@Autowired
private Notifications notifications;
@Subscribe
public void onAfterSave(final AfterSaveEvent event) {
notifications.create("Entity saved successfully")
.withType(Notifications.Type.SUCCESS)
.withPosition(Notification.Position.TOP_END)
.show();
}
Диаграммы
Закрытие экрана деталей сущности
На следующей диаграмме показан процесс сохранения изменений и закрытия экрана деталей действием detail_saveClose: