Статьи

Реализация динамического обработчика диалогов с функциональным программированием

В моем предыдущем посте я упомянул типичный случай использования, когда нам нужно программно проверить, является ли текущая транзакция грязной, и уведомить пользователя об этом, прежде чем что-то делать. Например: «У вас есть несохраненные изменения, которые будут потеряны, вы хотите продолжить?».

Предположим, что нам нужно уведомить пользователя о грязных транзакциях во многих местах приложения, при переходе от одного представления к другому, при нажатии кнопки «Поиск», при вызове метода бизнес-службы и т. Д. Итак, в каждом отдельном сценарии нам нужно выполнить разные вещи после того, как пользователь подтверждает, что он хочет продолжить. Это означает, что наш слушатель диалога должен каким-то образом знать, о чем идет речь и что делать дальше.

Решением может быть добавление пользовательского атрибута к компоненту 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, являются их собственными.