ADF中,当用户关闭编辑窗口时,如何弹出确认窗口
在ADF中,可以在弹出窗口(af:popup)上添加表单来编辑数据。用户可以点击弹出窗口右上角的关闭按钮,来关闭弹出窗口。但是当用户希望在关闭按钮前弹出一个确认窗口,用户可以选择Yes或者No,来决定是否停留在当前的页面时,该如何实现呢?因为在ADF中,当用户点击了关闭按钮之后,弹出窗口是在客户端关闭完之才分发给服务端,因此即使在服务端添加了显示确认窗口的代码后,因为原来的父窗口已经关闭了,所以不能满足需求。所以虽然这是个简单的需求,我们需要做一些特殊的处理。
直观的有下面的两个思路。
思路一:
1. 给父窗口添加PopupCanceledEvent的服务端监听器,首先获得父窗口的对象将它显示出来,然后获得确认窗口的对象将它显示出来。
2. 给确认窗口添加服务端的DialogEvent的监听器,当用户选择Yes时候,关闭父窗口;否则停留在父窗口。
给编辑窗口添加服务端PopupCanceledEvent监听器:
<af:popup id="p2" binding="#{UserManagedBean.userPopup}" popupCanceledListener="#{UserManagedBean.popupCancelListener}"> <af:panelWindow id="pw4" title="Edit User" modal="true"> <f:subview id="userSubview "> <jsp:include page="/pages/editUser.jsff"/> </f:subview> </af:panelWindow> </af:popup>
监听器Java代码:
public void popupCancelListener(PopupCanceledEvent popupCanceledEvent) { RichPopup userPop = (RichPopup)popupCanceledEvent.getComponent(); userPop.show(new RichPopup.PopupHints()); getCloseConfirmPopup().show(new RichPopup.PopupHints()); }
很不幸,这个思路在大多数情况下是不可行的。因为编辑窗口上定义的控件大多数都是非autoSubmit的。而ADF对于PopupCanceledEvent这一类型的事件是不会更新Model层的数据的。因此虽然我们通过代码又打开了已经关闭编辑窗口,但是在生成请求响应时(包括新的编辑窗口html代码,对应的javascript对象,以及将二者绑定到一起的javascript代码等),会使用当前的Model层的数据,显然最终导致了用户输入的数据的丢失(除非控件是autoSubmit的,因为此时Model层在控件值发生变化的时候已经被ADF框架更新了)。这个显然是不符合需求的。
思路二:
1. 给父窗口添加popupCanceled客户端监听器,首先获得父窗口的对象将它显示出来,然后获取确认窗口的对象将它显示出来,最后取消popupCanceled事件的传递。
2. 给确认窗口添加服务端的DialogEvent的监听器,当用户选择Yes时候,关闭父窗口;否则停留在父窗口。
给编辑窗口添加客户端popupCanceled监听器:
<af:popup id="p2" binding="#{UserManagedBean.userPopup}" <af:clientListener type="popupCanceled" method="onCloseConfirmPopup"/> <af:panelWindow id="pw4" title="Edit User" modal="true"> <f:subview id="userSubview"> <jsp:include page="/pages/editUser.jsff"/> </f:subview> </af:panelWindow> </af:popup>
监听器Javascript代码:
function onCloseConfirmPopup(evt){ var eventSource = evt.getSource(); eventSource.show(); //the confirm popup is defined in editUser.jsff file. var confirmPop = AdfPage.PAGE.findComponentByAbsoluteId("userSubview:confirmPopup"); confirmPop.show(); evt.cancel(); }
此思路将显示确认窗口的代码移动到了客户端,因此有效的避免了因为PopupCanceledEvent向服务器端分发而导致的用户数据的丢失问题。因此此思路是可行的。
确认窗口的服务端DialogEvent的监听器:
public void closeConfirmPopListener(DialogEvent dialogEvent) { if (Outcome.no.equals(dialogEvent.getOutcome())) { return; } findUserPopup().hide(); }
相关的几个文档链接:
Handling the af:dialog Ok and CANCEL buttons