在我以前的文章中,我提到了一个常见的用例,当我们需要以编程方式检查当前事务是否脏了,并在做某件事之前通知用户有关该事务的信息。 就像“您有未保存的更改将丢失,要继续吗?”。
假设我们需要在应用程序中许多位置,从一个视图导航到另一个视图,单击“搜索”按钮,调用业务服务方法等时通知用户有关交易不干净的情况。因此,在每种情况下,我们都需要做在用户确认他们要继续之后的其他事情。 这意味着我们的对话侦听器应该以某种方式知道它的全部内容以及下一步要做什么。
解决方案可以是向af:dialog组件添加自定义属性,该自定义属性指向当用户在对话框中单击“是”时将要调用的函数:
<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>
在这种情况下,对话框侦听器可能如下所示:
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功能接口的对象。
我们的utils中有一个方法显示带有对话框的弹出窗口:
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 Lambda表达式的功能并实现按钮动作侦听器,如下所示:
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");
}
基于此技术,我们可以实现一个声明性组件,用作具有动态内容和动态处理程序的对话框。
而已!