Recently I developed a page where I provided edit functionality for a table row in a Popup with Dialog having Save/Cancel buttons.
If user add/edit/remove row and click Save, the data is getting saved. And if user clicks on Cancel button, the updated data/action inside popup needs to be revert back, but its not happening. af:resetActionListener won't help.
Initially I thought of execute rollback when user clicked on Cancel button, but it impacts other changes in the page. So I tried below steps to perform partial rollback to revert only changes done in Popup. Here I used similar save point concept explained in Link.
1. Add following methods to Bean class to create/restore/remove save point.
public static DCBindingContainer getDCBindingContainer() {
return (DCBindingContainer)getBindingContainer();
}
public static BindingContainer getBindingContainer() {
return (BindingContainer)resolveExpression("#{bindings}");
}
public static Object resolveExpression(String expression) {
FacesContext facesContext = getFacesContext();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = facesContext.getELContext();
ValueExpression valueExp =
elFactory.createValueExpression(elContext, expression,
Object.class);
return valueExp.getValue(elContext);
}
public static FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
public void createSavePoint(ActionEvent actionEvent) {
DCBindingContainer bindingContainer = getDCBindingContainer();
DCDataControl dcDataControl = bindingContainer.getDataControl();
String spID = (String)dcDataControl.createSavepoint();
AdfFacesContext.getCurrentInstance().getPageFlowScope().put("spID",
spID);
System.out.println("Save Point Created: " + spID);
}
public void restoreSavePoint() {
String spID =
(String)AdfFacesContext.getCurrentInstance().getPageFlowScope().get("spID");
DCBindingContainer bindingContainer = getDCBindingContainer();
DCDataControl dcDataControl = bindingContainer.getDataControl();
dcDataControl.restoreSavepoint(spID);
System.out.println("Save Point Restored: " + spID);
}
public void removeSavePoint() {
AdfFacesContext.getCurrentInstance().getPageFlowScope().put("spID",
null);
System.out.println("Save Point Removed");
}
2. Add button and call createSavePoint method when clicked on it. Since popup and also actionListener to be called at same time, set the showPopupBehaviour's TriggerType as Click.
<af:commandButton text="Edit" id="cbj4"
partialSubmit="true"
actionListener="#{pageFlowScope.editBean.createSavePoint}">
<af:showPopupBehavior triggerType="click"
popupId="editPop"/>
</af:commandButton>
3. Set ContentDelivery of the af:popup to lazyUncached to display value from the base attribute. Set af:dialog 'type' as 'yesNo' and 'closeIconVisible' to 'false'.Add dialogListener method to listen to actions from Dialog.
<af:popup id="editPop"
contentDelivery="lazyUncached"
<af:dialog id="d451" type="yesNo" title="Edit Host"
dialogListener="#{pageFlowScope.editBean.editDialogListener}"
closeIconVisible="false"
affirmativeTextAndAccessKey="Save"
noTextAndAccessKey="Cancel">
<af:table value=" ..../>
</af:dialog>
</af:popup>
4. Add following Dialog Listener method to Bean class to call restore/remove save point methods based on dialog action.
public void editDialogListener(DialogEvent dialogEvent) {
Outcome outcome = dialogEvent.getOutcome();
System.out.println("Outcome: " + outcome);
if (outcome == Outcome.yes) {
removeSavePoint();
} else {
restoreSavePoint();
}
}
5. Add Dialog component id to table's Partial trigger property to refresh when Save/Cancel performed.
<af:table partialTriggers="d451" value=" ..../>
If user add/edit/remove row and click Save, the data is getting saved. And if user clicks on Cancel button, the updated data/action inside popup needs to be revert back, but its not happening. af:resetActionListener won't help.
Initially I thought of execute rollback when user clicked on Cancel button, but it impacts other changes in the page. So I tried below steps to perform partial rollback to revert only changes done in Popup. Here I used similar save point concept explained in Link.
1. Add following methods to Bean class to create/restore/remove save point.
public static DCBindingContainer getDCBindingContainer() {
return (DCBindingContainer)getBindingContainer();
}
public static BindingContainer getBindingContainer() {
return (BindingContainer)resolveExpression("#{bindings}");
}
public static Object resolveExpression(String expression) {
FacesContext facesContext = getFacesContext();
Application app = facesContext.getApplication();
ExpressionFactory elFactory = app.getExpressionFactory();
ELContext elContext = facesContext.getELContext();
ValueExpression valueExp =
elFactory.createValueExpression(elContext, expression,
Object.class);
return valueExp.getValue(elContext);
}
public static FacesContext getFacesContext() {
return FacesContext.getCurrentInstance();
}
public void createSavePoint(ActionEvent actionEvent) {
DCBindingContainer bindingContainer = getDCBindingContainer();
DCDataControl dcDataControl = bindingContainer.getDataControl();
String spID = (String)dcDataControl.createSavepoint();
AdfFacesContext.getCurrentInstance().getPageFlowScope().put("spID",
spID);
System.out.println("Save Point Created: " + spID);
}
public void restoreSavePoint() {
String spID =
(String)AdfFacesContext.getCurrentInstance().getPageFlowScope().get("spID");
DCBindingContainer bindingContainer = getDCBindingContainer();
DCDataControl dcDataControl = bindingContainer.getDataControl();
dcDataControl.restoreSavepoint(spID);
System.out.println("Save Point Restored: " + spID);
}
public void removeSavePoint() {
AdfFacesContext.getCurrentInstance().getPageFlowScope().put("spID",
null);
System.out.println("Save Point Removed");
}
2. Add button and call createSavePoint method when clicked on it. Since popup and also actionListener to be called at same time, set the showPopupBehaviour's TriggerType as Click.
<af:commandButton text="Edit" id="cbj4"
partialSubmit="true"
actionListener="#{pageFlowScope.editBean.createSavePoint}">
<af:showPopupBehavior triggerType="click"
popupId="editPop"/>
</af:commandButton>
3. Set ContentDelivery of the af:popup to lazyUncached to display value from the base attribute. Set af:dialog 'type' as 'yesNo' and 'closeIconVisible' to 'false'.Add dialogListener method to listen to actions from Dialog.
<af:popup id="editPop"
contentDelivery="lazyUncached"
<af:dialog id="d451" type="yesNo" title="Edit Host"
dialogListener="#{pageFlowScope.editBean.editDialogListener}"
closeIconVisible="false"
affirmativeTextAndAccessKey="Save"
noTextAndAccessKey="Cancel">
<af:table value=" ..../>
</af:dialog>
</af:popup>
4. Add following Dialog Listener method to Bean class to call restore/remove save point methods based on dialog action.
public void editDialogListener(DialogEvent dialogEvent) {
Outcome outcome = dialogEvent.getOutcome();
System.out.println("Outcome: " + outcome);
if (outcome == Outcome.yes) {
removeSavePoint();
} else {
restoreSavePoint();
}
}
5. Add Dialog component id to table's Partial trigger property to refresh when Save/Cancel performed.
<af:table partialTriggers="d451" value=" ..../>