Thursday, February 25, 2010

Use ice:commandButton to update UI fields bypassing validation

How to trigger an action that refreshes or updates ui input components bypassing JSF validation? Suppose you have a form with address fields where data can be entered by hand or copied from somewhere (a previously entered screen maybe) at the click of a button. You'd usually want to validate/convert these fields before data gets to its final destination in the backing bean.

You can use a command button to trigger a bean action that would copy data but the problem with this approach is that if there are errors (for example, if the user clicked Save with empty fields) on the screen JSF will prevent the button from submitting. You might try to set the button's immediate attribute to true which will force JSF to skip validation and ignore errors on UI components, but it will also mean that changes to data are not transferred to DOM and hence aren't seen by ICEfaces - you will see the action being triggered but the UI will not reflect the changes.

Using the immediate attribute is the simplest way to bypass validation but we need a way to get the new values from action to the UI. The simple trick is to bind the container where the UI data components reside to a backing bean property and clear it's children (the UI components) in the action method. This forces ICEfaces to fetch all data to rebuild components at which point it will see the changed values.

In short: make the command button immediate and bind the panel grid containing UI components with data to a backing bean property. In the action triggered by the button clear the grid to force ICEfaces to restore data. Here are the code snippets:


JSPX: put a container - a panel grid in this case - with ui fields:

<ice:panelGrid columns="4" binding = "#{backingBean.panelGrid}">
<!-- Add input components inside the grid>
</ice:panelGrid>


Add a command button:

<ice:commandButton value = "Copy Address"
immediate = "true"
action = "#{backingBean.copyAddress}"
actionListener="#{backingBean.copyAddressEvent}" />


Backing bean:

//Bind the grid to HtmlPanelGrid
public HtmlPanelGrid getPanelGrid() {
return panelGrid;
}

public void setPanelGrid(HtmlPanelGrid panelGrid) {
this.panelGrid = panelGrid;
}

//Do data updates and clear the grid
public void copyAddress(ActionEvent ae) {
thisAddress.streetAddress = otherAddress.streetAddress;
thisAddress.city = otherAddress.city;
getPanelGrid().getChildren().clear();
}

No comments:

 
1.