0

The website I'm working on has multiple types of users: basic, advanced, pro. The form is already customized depending on user type by surround some fields with a conditional container tag like <h:panelGroup rendered="#{userType != 'basic'}">. This works well for just hiding some fields from the basic user..

Now, my customer's (horrible) new idea is to place some fields in one or another section, depending on the user type. Below is a simplified example. "Field 2" occurs in the 1st section for 'basic' users and in the 2nd section for all others. I've already evaded the "Duplicate ID" problem by assigning id "field_2a" to the second occurrence, but the value and the binding are the same.

The binding is the problem. It looks like JSF evaluates all expressions and bindings before removing stuff that is not rendered. As a result, #{formBean.field_2_inputElement} is always bound to field_2a and never to field_2. So it does not work for basic users.

I have 2 ideas to solve this, but both are ugly and I'm looking for a better option.

  1. Duplicate the whole JSF fragment containing the form, and include the fragment matching the user type: <ui:include src="/path/to/#{userBean.userType}/form.xhtml"/> (yes, this works, I've tested it).
    Downside: I'll have to make all future changes an both files synchronously.
  2. Have separate bindings and use the matching one by checking the user type in the formBean.
    Downside: It makes the code ugly.

Any ideas for a 3rd and better option?

    <h3>Some section heading</h3>

    <h:outputLabel id="field_1_label"
                   for="field_1"
                   value="Field 1: "/>
    <h:inputText id="field_1"
                 value="{#formBean.field_1}"/>

    <h:panelGroup rendered="#{userBean.userType == 'basic'}">
      <h:outputLabel id="field_2_label"
                     for="field_2"
                     value="Field 2: "/>
      <h:inputText id="field_2"
                   value="{#formBean.field_2}"
                   binding="#{formBean.field_2_inputElement}"/>
    </h:panelGroup>

    <h:panelGroup rendered="#{userBean.userType != 'basic'}">

      <h3>Some section heading</h3>

      <h:outputLabel id="field_3_label"
                     for="field_3"
                     value="Field 3: "/>
      <h:inputText id="field_3"
                   value="{#formBean.field_3}"/>

      <h:outputLabel id="field_2a_label"
                     for="field_2"
                     value="Field 2: "/>
      <h:inputText id="field_2a"
                   value="{#formBean.field_2}"
                   binding="#{formBean.field_2_inputElement}"/>
    </h:panelGroup>

    <h3>Some section heading</h3>
  • In this simplified example, the binding is not needed. But in my real-world webapp, it is needed for cross-field validation – user9964388 Feb 03 '23 at 13:05

0 Answers0