Class ResetInputAjaxActionListener
- java.lang.Object
-
- org.omnifaces.eventlistener.DefaultPhaseListener
-
- org.omnifaces.eventlistener.ResetInputAjaxActionListener
-
- All Implemented Interfaces:
ActionListener
,FacesListener
,PhaseListener
,Serializable
,EventListener
public class ResetInputAjaxActionListener extends DefaultPhaseListener implements ActionListener
The
ResetInputAjaxActionListener
will reset input fields which are not executed during ajax submit, but which are rendered/updated during ajax response. This will prevent those input fields to remain in an invalidated state because of a validation failure during a previous request. This is very useful for cases where you need to update one form from another form by for example a modal dialog, or when you need a cancel/clear button.How does it work? First, here are some Faces facts:
- When Faces validation succeeds for a particular input component during the validations phase, then the submitted
value is set to
null
and the validated value is set as local value of the input component. - When Faces validation fails for a particular input component during the validations phase, then the submitted value is kept in the input component.
- When at least one input component is invalid after the validations phase, then Faces will not update the model values for any of the input components. Faces will directly proceed to render response phase.
- When Faces renders input components, then it will first test if the submitted value is not
null
and then display it, else if the local value is notnull
and then display it, else it will display the model value. - As long as you're interacting with the same Faces view, you're dealing with the same component state.
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 Faces to display the model value which was edited during invoke action. Otherwise Faces 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:Register it as
<phase-listener>
infaces-config.xml
. It'll be applied to every single ajax action throughout the webapp, on bothUIInput
andUICommand
components.<lifecycle> <phase-listener>org.omnifaces.eventlistener.ResetInputAjaxActionListener</phase-listener> </lifecycle>
Or register it as
<action-listener>
infaces-config.xml
. It'll only be applied to ajax actions which are invoked by anUICommand
component such as<h:commandButton>
and<h:commandLink>
.<application> <action-listener>org.omnifaces.eventlistener.ResetInputAjaxActionListener</action-listener> </application>
Or register it as
<f:actionListener>
on the invidivualUICommand
components where this action listener is absolutely necessary to solve the concrete problem. Note that it isn't possible to register it on the individualUIInput
components using the standard Faces tags.<h:commandButton value="Update" action="#{bean.updateOtherInputs}"> <f:ajax execute="currentInputs" render="otherInputs" /> <f:actionListener type="org.omnifaces.eventlistener.ResetInputAjaxActionListener" /> </h:commandButton>
This works with standard Faces, 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 Faces 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 inUIInput
components. There are ways with help ofSystemEventListener
, but it ended up to be too clumsy.See also:
Faces spec issue 1060- Author:
- Bauke Scholtz
- See Also:
- Serialized Form
-
-
Field Summary
-
Fields inherited from interface jakarta.faces.event.ActionListener
TO_FLOW_DOCUMENT_ID_ATTR_NAME
-
-
Constructor Summary
Constructors Constructor Description ResetInputAjaxActionListener()
Construct a new reset input ajax action listener.ResetInputAjaxActionListener(ActionListener wrapped)
Construct a new reset input ajax action listener around the given wrapped action listener.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description void
beforePhase(PhaseEvent event)
Delegate to theprocessAction(ActionEvent)
method when this action listener is been registered as a phase listener so that it get applied on all ajax requests.void
processAction(ActionEvent event)
Handle the reset input action as follows, only and only if the current request is an ajax request and thePartialViewContext.getRenderIds()
does not return an empty collection nor is the same asPartialViewContext.getExecuteIds()
: find allEditableValueHolder
components based onPartialViewContext.getRenderIds()
and if the component is not covered byPartialViewContext.getExecuteIds()
, then invokeEditableValueHolder.resetValue()
on the component.-
Methods inherited from class org.omnifaces.eventlistener.DefaultPhaseListener
afterPhase, getPhaseId
-
-
-
-
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>
infaces-config.xml
.
-
ResetInputAjaxActionListener
public ResetInputAjaxActionListener(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>
infaces-config.xml
.- Parameters:
wrapped
- The wrapped action listener.
-
-
Method Detail
-
beforePhase
public void beforePhase(PhaseEvent event)
Delegate to theprocessAction(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 interfacePhaseListener
- Overrides:
beforePhase
in classDefaultPhaseListener
- See Also:
processAction(ActionEvent)
-
processAction
public void processAction(ActionEvent event)
Handle the reset input action as follows, only and only if the current request is an ajax request and thePartialViewContext.getRenderIds()
does not return an empty collection nor is the same asPartialViewContext.getExecuteIds()
: find allEditableValueHolder
components based onPartialViewContext.getRenderIds()
and if the component is not covered byPartialViewContext.getExecuteIds()
, then invokeEditableValueHolder.resetValue()
on the component.- Specified by:
processAction
in interfaceActionListener
- Throws:
IllegalArgumentException
- When one of the client IDs resolved to anull
component. This would however indicate a bug in the concretePartialViewContext
implementation which is been used.
-
-