Search code examples
jsfprimefacesjsf-2.2

How to reset input components on change of <p:selectOneMenu> after certain validations are violated


I'm populating <p:selectOneMenu> from a database which contains a list of zones, when a JSF page loaded.

When a zone in this menu is selected, a set of <p:inputText> is displayed in which a user can insert charge that corresponds to product weight which is to be transferred by a transporter to the selected zone in the menu. This can be shown in the following snap shot.

enter image description here

As can be seen, when non numeric values are entered by a user, validation violations occurs, when the given save button <p:commandButton> is pressed (the numbers displayed on top of each text field correspond to weight).

If a user now change the zone in the menu - the first panel without pressing the reset button, the data corresponds to that newly selected zone is loaded in these text fields only when the reset button is pressed as follows (because of validation violation)..

enter image description here

So, how to load data after previous validation violation, if an item (zone) is changed in the menu?

The change event of <p:selectOneMenu>, in this case should do the function something like which is done by <p:resetInput>.

Hope you will be able to understand what I mean :).


Solution

  • Basically, you need the functionality provided by <p:resetInput> inside <p:ajax> of a <p:selectOneMenu>.

    Imagine that you currently have a:

    <h:form>
        <p:selectOneMenu id="zone">
            <f:selectItems ... />
            <p:ajax listener="#{bean.changeZone}" update="data" />
        </p:selectOneMenu>
    
        <p:panel id="data">
            ...
        </p:panel>
    </h:form>
    

    Your solution depends on PrimeFaces version used.

    PrimeFaces 4.0+

    Set the resetValues attribute of <p:ajax> to true. This will reset the values of components covered by update attribute.

    <p:ajax listener="#{bean.changeZone}" update="data" resetValues="true" />
    

    PrimeFaces 3.4+

    The resetValues was only introduced in 4.0. If you're still on 3.4+ and you cannot ugrade, then use <p:resetInput>. The only issue is that it requires being placed in a component implementing ActionSource such as UICommand components. Your best bet is to let <p:remoteCommand> take over the <p:ajax> change listener job. Therein you can put a <p:resetInput>.

    Then this change should do:

    <h:form>
        <p:selectOneMenu id="zone" onchange="changeZone()">
            <f:selectItems ... />
        </p:selectOneMenu>
        <p:remoteCommand name="changeZone" process="@this zone" action="#{bean.changeZone}" update="data">
            <p:resetInput target="data" />
        </p:remoteCommand>  
    
        <p:panel id="data">
            ...
        </p:panel>
    </h:form>
    

    Don't forget to remove the AjaxBehaviorEvent argument from the listener method. It's useless in this particular case anyway.

    OmniFaces

    In case you've OmniFaces at hands, then you can also use its ResetInputAjaxActionListener. It was actually the inspiration behind the later introduced <f|p:ajax resetValues> and <p:resetInput>. The OmniFaces ResetInputAjaxActionListener can be activated in multiple ways, even application-wide as a phase listener:

    <lifecycle>
        <phase-listener>org.omnifaces.eventlistener.ResetInputAjaxActionListener</phase-listener>
    </lifecycle>
    

    This will automatically reset values of all components specified in update attribute which are not covered by execute attribute.