Search code examples
validationjsfjsf-2postbackviewparams

How to retain f:viewParam values after postback with validation failed


I have xhtml page with simple form. This page is using for several data tables. To specify data table (and so on), I use GET request parameters. xhtml page receive it through

  <f:metadata>
    <f:viewParam id="page" name="page" value="#{itemsBean.page}"/>
  </f:metadata>

and pass again by the navigation rules like

  <navigation-case>
  <description>
  Global rule for going to the items page from any page  
  </description>
  <from-outcome>items</from-outcome>
  <to-view-id>/items.xhtml</to-view-id>
  <redirect>
    <view-param>
      <name>page</name>
      <value>#{itemsBean.page}</value>
    </view-param>  
  </redirect>  
  </navigation-case>

But if I use inputs in the xhtml file like this

  <h:inputText id="itemName" value="#{itemsBean.name}" 
    required="true" requiredMessage="Value for this field required!"/>

I cannot restore view param after trying to accepting form with no text in input. I tried to use hidden input for passing parameters

<h:inputHidden id="page" value="#{itemsBean.page}" />

, but seems like validation runs before and itemsBean.page is still empty. itemsBean is RequestScoped. What things I do wrong? How can I pass the param?

Thank you for wasting your time.


Solution

  • You need to keep passing request parameters to the subsequent request. In "plain vanilla" HTML you'd indeed have used <input type="hidden"> for this, but the JSF <h:inputHidden> unfortunately doesn't work that way. In case of a general validation failure, caused by another input field, the model value associated with <h:inputHidden> won't be updated at all.

    You should be using a <f:param> in the UICommand component instead to retain request parameters for the subsequent request. E.g.

    <h:commandButton ...>
        <f:param name="page" value="#{param.page}" />
    </h:commandButton>
    

    Alternatively, you can use the <o:form> of the OmniFaces JSF utility library, it basically extends the <h:form> with an additional attribute includeViewParams which enables you to retain the view parameters for the subsequent request in the form action URL.

    <o:form includeViewParams="true">
        ...
    </o:form>
    

    This may end up to be easier if you have multiple command buttons/links and ajax actions, and this would be the only way in case you'd like to retain the same URL during non-ajax postbacks.