在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