1

I have a JSF 2.2 form comprised of an input text field and a pair of radio buttons displayed inline. Given the known limitations on radio button groups in JSF 2.2, I'm using the technique outlined by BalusC in this blog post. We cannot upgrade to JSF 2.3, as this is a Weblogic application and we're currently locked on Weblogic 12.2 (JavaEE 7).

While this technique works fine when a valid form is submitted, the problem is that if an invalid form is submitted, then the user's radio button selection is lost, and it resets to the last valid value (or initial value).

Here's an example of how I'm defining the radio button pair, using a h:inputHidden element and linking its binding attribute with the name attributes of the individual radio buttons (for their group ID).

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://xmlns.jcp.org/jsf/html"
                xmlns:f="http://xmlns.jcp.org/jsf/core"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:jsf="http://xmlns.jcp.org/jsf"
                xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
                
    <div class="form-group">

        <h:outputLabel for="heightInput"
                       value="Height"
                       styleClass="col-xs-6" />
        <div class="col-xs-6">
            <h:inputText id="heightInput"
                         value="#{modelBean.height}"
                         required="true" />
        </div>
        
        <div class="col-xs-12">
        
            <div class="radio-inline">
                <h:outputLabel for="heightCentimeters">
                    <input type="radio"
                           jsf:id="heightCentimeters"
                           pt:name="#{hiddenHeightUnitSelection.clientId}"
                           value="CENTIMETERS"
                           pt:checked="#{modelBean.heightUnit eq 'CENTIMETERS' ? 'checked' : null}" />
                    Centimeters
                </h:outputLabel>
            </div>
            
            <div class="radio-inline">
                <h:outputLabel for="heightInches">
                    <input type="radio"
                           jsf:id="heightInches"
                           pt:name="#{hiddenHeightUnitSelection.clientId}"
                           value="INCHES"
                           pt:checked="#{modelBean.heightUnit eq 'INCHES' ? 'checked' : null}" />
                    Inches
                </h:outputLabel>
            </div>
            
            <h:inputHidden id="heightUnitSelection"
                           binding="#{hiddenHeightUnitSelection}"
                           value="#{modelBean.heightUnit}"
                           rendered="#{facesContext.currentPhaseId.ordinal ne 6}" />
        </div>
    </div>

</ui:composition>

How can I preserve the user's radio button selection in the event an invalid form is submitted? The model is never updated with their selection. Other form elements preserve their values across form submissions, even when validation errors exist. How can I have my radio button group behave similarly?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Kevin Swan
  • 147
  • 12

1 Answers1

1

Indeed, the checked attribute is comparing the model value directly.

pt:checked="#{modelBean.heightUnit eq 'CENTIMETERS' ? 'checked' : null}"

The model value is updated during UPDATE_MODEL_VALUES phase, but it won't be executed when there's a validation error encountered during PROCESS_VALIDATIONS phase.

Basically, you want to check the submitted value instead of the model value. This is already covered by the logic behind UIInput#getValue(). In your specific case, you want to compare against the value of the <h:inputHidden> instead.

pt:checked="#{hiddenHeightUnitSelection.value eq 'CENTIMETERS' ? 'checked' : null}"

The blog article linked in your question has in the meanwhile been updated.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555