- All Implemented Interfaces:
ActionListener,FacesListener,PhaseListener,Serializable,EventListener
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
nulland 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
nulland then display it, else if the local value is notnulland 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 bothUIInputandUICommandcomponents.<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 anUICommandcomponent 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 invidivualUICommandcomponents where this action listener is absolutely necessary to solve the concrete problem. Note that it isn't possible to register it on the individualUIInputcomponents 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>
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 in UIInput components. There are ways with help of SystemEventListener, but it ended up to be
too clumsy.
See also:
Faces spec issue 1060
- Author:
- Bauke Scholtz
- See Also:
-
Field Summary
Fields inherited from interface jakarta.faces.event.ActionListener
TO_FLOW_DOCUMENT_ID_ATTR_NAME -
Constructor Summary
ConstructorsConstructorDescriptionConstruct a new reset input ajax action listener.Construct a new reset input ajax action listener around the given wrapped action listener. -
Method Summary
Modifier and TypeMethodDescriptionvoidbeforePhase(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.voidprocessAction(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 allEditableValueHoldercomponents 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 Details
-
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
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 Details
-
beforePhase
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:
beforePhasein interfacePhaseListener- Overrides:
beforePhasein classDefaultPhaseListener- See Also:
-
processAction
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 allEditableValueHoldercomponents based onPartialViewContext.getRenderIds()and if the component is not covered byPartialViewContext.getExecuteIds(), then invokeEditableValueHolder.resetValue()on the component.- Specified by:
processActionin interfaceActionListener- Throws:
IllegalArgumentException- When one of the client IDs resolved to anullcomponent. This would however indicate a bug in the concretePartialViewContextimplementation which is been used.
-