В моем предыдущем посте я упомянул типичный случай использования, когда нам нужно программно проверить, является ли текущая транзакция грязной, и уведомить пользователя об этом, прежде чем что-то делать. Например: «У вас есть несохраненные изменения, которые будут потеряны, вы хотите продолжить?».
Предположим, что нам нужно уведомить пользователя о грязных транзакциях во многих местах приложения, при переходе от одного представления к другому, при нажатии кнопки «Поиск», при вызове метода бизнес-службы и т. Д. Итак, в каждом отдельном сценарии нам нужно выполнить разные вещи после того, как пользователь подтверждает, что он хочет продолжить. Это означает, что наш слушатель диалога должен каким-то образом знать, о чем идет речь и что делать дальше.
Решением может быть добавление пользовательского атрибута к компоненту af: dialog, указывающего на функцию, которая будет вызываться, когда пользователь нажимает «Да» в диалоговом окне:
|
01
02
03
04
05
06
07
08
09
10
11
|
<af:popup id="pDirtyTransaction" contentDelivery="lazyUncached"> <af:dialog title="Warning" type="yesNo" closeIconVisible="false" id="dDirtyTransaction" dialogListener="#{theBean.dirtyTransactionDialogListener}"> <af:outputText value="You have unsaved changes, do you want to continue?" id="ot1"/> <f:attribute name="dialogHandler" value=""/> </af:dialog></af:popup> |
В этом случае слушатель диалога может выглядеть так:
|
1
2
3
4
5
6
7
8
|
public void dirtyTransactionDialogListener(DialogEvent dialogEvent) { Map attrs = dialogEvent.getComponent().getAttributes(); Consumer<Boolean> dialogHandler = (Consumer) attrs.get("dialogHandler"); if (dialogHandler != null) { dialogHandler.accept(dialogEvent.getOutcome() == DialogEvent.Outcome.yes); attrs.put("dialogHandler",null); } } |
Здесь мы ожидаем, что атрибут dialogHandler указывает на объект, реализующий функциональный интерфейс Consumer .
В наших утилитах есть метод, показывающий всплывающее окно с диалогом:
|
01
02
03
04
05
06
07
08
09
10
|
public static void showDirtyTransactionPopup(Consumer dialogHandler) { if (dialogHandler != null) { JSFUtil.findComponent("dDirtyTransaction").getAttributes(). put("dialogHandler",dialogHandler); } RichPopup popup = (RichPopup) JSFUtil.findComponent("pDirtyTransaction"); popup.show(new RichPopup.PopupHints());} |
Давайте использовать этот подход в простом сценарии. В нашем потоке задач View1 и View2 есть два вида деятельности. Пользователь нажимает кнопку для перехода от одного вида к другому. Во время навигации нам нужно проверить, не является ли текущая транзакция грязной, и спросить пользователя, хотят ли они продолжить. Мы можем использовать мощь лямбда-выражений Java 8 и реализовать слушатель действия кнопки следующим образом:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
|
public void buttonActionListener(ActionEvent actionEvent) { if (Utils.isTransactionDirty()) { Utils.showDirtyTransactionPopup((yesOutcome) -> { //the code below will be invoked by the dialog listener //when the user clicks a button on the dialog if ((Boolean) yesOutcome) { //the user has agreed to proceed, //so let's rollback the current transaction Utils.getCurrentRootDataControl().rollbackTransaction(); //and queue an action event for this button again new ActionEvent(actionEvent.getComponent()).queue(); } }); } else //just navigate to View2 Utils.handleNavigation("goView2");} |
На основе этой техники мы могли бы реализовать декларативный компонент, служащий в качестве диалога с динамическим содержимым и динамическим обработчиком.
Это оно!
| Опубликовано на Java Code Geeks с разрешения Евгения Федоренко, партнера нашей программы JCG . См. Оригинальную статью здесь: Реализация динамического обработчика диалогов с функциональным программированием
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |