org.omnifaces.eventlistener
Class ResetInputAjaxActionListener

java.lang.Object
  extended by org.omnifaces.eventlistener.DefaultPhaseListener
      extended by org.omnifaces.eventlistener.ResetInputAjaxActionListener
All Implemented Interfaces:
java.io.Serializable, java.util.EventListener, javax.faces.event.ActionListener, javax.faces.event.FacesListener, javax.faces.event.PhaseListener

public class ResetInputAjaxActionListener
extends DefaultPhaseListener
implements javax.faces.event.ActionListener

Use this action listener when you want to partially (ajax) render input fields which are not executed during submit, but which are possibly in an invalidated state because of a validation failure during a previous request. Those input fields will be resetted so that they are not in an invalidated state anymore.

How does it work? First, here are some JSF facts:

So, when the validation has failed for a particular form submit and you happen to need to update the values of input fields by a different ajax action or even a different ajax form (e.g. populating a field depending on a dropdown selection or the result of some modal dialog form, etc), then you basically need to reset the target input components in order to get JSF to display the model value which was edited during invoke action. Otherwise JSF will still display its local value as it was during the validation failure and keep them in an invalidated state.

The ResetInputAjaxActionListener is designed to solve exactly this problem. There are basically three ways to configure and use it:

This works with standard JSF, PrimeFaces and RichFaces actions. Only for RichFaces there's a reflection hack, because its ExtendedPartialViewContextImpl always returns an empty collection for render IDs. See also RF issue 11112.

Design notice: being a phase listener was mandatory in order to be able to hook on every single ajax action as standard JSF API does not (seem to?) offer any ways to register some kind of AjaxBehaviorListener in an application wide basis, let alone on a per <f:ajax> tag basis, so that it also get applied to ajax actions in UIInput components. There are ways with help of SystemEventListener, but it ended up to be too clumsy.

Author:
Bauke Scholtz
See Also:
Serialized Form

Constructor Summary
ResetInputAjaxActionListener()
          Construct a new reset input ajax action listener.
ResetInputAjaxActionListener(javax.faces.event.ActionListener wrapped)
          Construct a new reset input ajax action listener around the given wrapped action listener.
 
Method Summary
 void beforePhase(javax.faces.event.PhaseEvent event)
          Delegate to the processAction(ActionEvent) method when this action listener is been registered as a phase listener so that it get applied on all ajax requests.
 void processAction(javax.faces.event.ActionEvent event)
          Handle the reset input action as follows, only and only if the current request is an ajax request and the PartialViewContext.getRenderIds() does not return an empty collection nor is the same as PartialViewContext.getExecuteIds(): find all EditableValueHolder components based on PartialViewContext.getRenderIds() and if the component is not covered by PartialViewContext.getExecuteIds(), then invoke EditableValueHolder.resetValue() on the component.
 
Methods inherited from class org.omnifaces.eventlistener.DefaultPhaseListener
afterPhase, getPhaseId
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ResetInputAjaxActionListener

public ResetInputAjaxActionListener()
Construct a new reset input ajax action listener. This constructor will be used when specifying the action listener by <f:actionListener> or when registering as <phase-listener> in faces-config.xml.


ResetInputAjaxActionListener

public ResetInputAjaxActionListener(javax.faces.event.ActionListener wrapped)
Construct a new reset input ajax action listener around the given wrapped action listener. This constructor will be used when registering as <action-listener> in faces-config.xml.

Parameters:
wrapped - The wrapped action listener.
Method Detail

beforePhase

public void beforePhase(javax.faces.event.PhaseEvent event)
Delegate to the processAction(ActionEvent) method when this action listener is been registered as a phase listener so that it get applied on all ajax requests.

Specified by:
beforePhase in interface javax.faces.event.PhaseListener
Overrides:
beforePhase in class DefaultPhaseListener
See Also:
processAction(ActionEvent)

processAction

public void processAction(javax.faces.event.ActionEvent event)
                   throws javax.faces.event.AbortProcessingException
Handle the reset input action as follows, only and only if the current request is an ajax request and the PartialViewContext.getRenderIds() does not return an empty collection nor is the same as PartialViewContext.getExecuteIds(): find all EditableValueHolder components based on PartialViewContext.getRenderIds() and if the component is not covered by PartialViewContext.getExecuteIds(), then invoke EditableValueHolder.resetValue() on the component.

Specified by:
processAction in interface javax.faces.event.ActionListener
Throws:
java.lang.IllegalArgumentException - When one of the client IDs resolved to a null component. This would however indicate a bug in the concrete PartialViewContext implementation which is been used.
javax.faces.event.AbortProcessingException