Sunday, November 16, 2008

Sticky Popup Values

Most of the problems that I will post about come from the project on which I am currently working. This post will be about one that has plagued us since the early days of our project, one which we thought we had fixed on more than one occasion; popups holding on to stale data.

Let's say a user clicks a button to edit values in a given table, in our app we use a popup to display a form in which the user can update the data. The user can make changes and click 'Ok' to save or click 'Cancel' to dismiss the changes; both actions dismiss the popup. Our problem was that if the user used 'Cancel', which has its immediate attribute set to 'true' (so that the validation does not occur), the next time they request for the popup to be displayed, it will display the values that were in the popup which we dismissed. This means that if we were editing row A in the table the first time, then cancelled, then decided to edit row B, the values from row A would appear. And every subsequent showing and canceling of the dialog would display the values from row A.

The issue turns out to be that since we skip the validation phase of ADF lifecycle, the values never get submitted out of the JSF model into the ADF model. The values therefore remain as values waiting to be submitted and are subsequently never excused from the fields in the popup. These values then replace whatever data is being displayed from the current row. So, if we were to click 'Ok' in the popup, they would then replace the values of the current row, and the next time the popup would be shown, it would actually be displaying the values from the current row as we expect (now that there are no stale values, because they have finally been submitted).

The trick we used to work around this issue is to basically clear out these un-submitted values from fields in the popup. We do this by iterating over all of the editable components that are in the dialog within the popup and using resetValue(). We generally pass in the dialog as the rootComponent.

public void resetStaleValues(UIComponent rootComponent){
Iterator iter = rootComponent.getFacetsAndChildren();
while (iter.hasNext()) {
UIComponent component = iter.next();
if (component instanceof UIXEditableValue) {
UIXEditableValue uiField = (UIXEditableValue)component;
uiField.resetValue();
}
resetStaleValues(component);
}

2 comments:

Unknown said...

Hi,

It's a gr8 article. I am facing same problem. Can you please elaborate how and where you are calling the resetStaleValues() method?

My popup dialog populates values from a backing bean in request scope.

Namita

Andrei said...

Thank you! This was a major pain.