Solved: SelectOneRadio with layout="custom" using datagrid not working

UI Components for JSF
Post Reply
csd1
Posts: 13
Joined: 31 Aug 2015, 15:35

23 Jun 2017, 16:01

Hi!

I am trying to use selectOneRadio with layout="custom" with p:dataGrid twice on page as shown in the following source code:

Code: Select all

<p:selectOneRadio id="select1" value="#{testModel.selectedText1}" layout="custom" >
  <f:selectItems value="#{testModel.texts1}" />
</p:selectOneRadio>

<p:dataGrid value="#{testModel.texts1}" columns="4" rowIndexVar="index" var="insuranceVar">
    <h:outputText value="#{insuranceVar}"/>
    <p:radioButton for="testForm:select1" itemIndex="#{index}"/>
    <h:outputText value="#{insuranceVar}"/>
    <h:outputText value="#{index}"/>              
</p:dataGrid>

<p:selectOneRadio id="select2" value="#{testModel.selectedText2}" layout="custom">
  <f:selectItems value="#{testModel.texts2}" />
</p:selectOneRadio>

<p:dataGrid value="#{testModel.texts2}" columns="4" rowIndexVar="index" var="insuranceVar">
  <h:outputText value="#{insuranceVar}"/>  
  <p:radioButton for="testForm:select2" itemIndex="#{index}"/>
  <h:outputText value="#{insuranceVar}"/>
  <h:outputText value="#{index}"/>
</p:dataGrid>
testModel.texts1 and testModel.texts2 are simple lists of strings:
(CLASSIC S, CLASSIC FAMILY S, EXTRA S, EXTRA FAMILY S)
(CLASSIC L, CLASSIC FAMILY L, EXTRA L, EXTRA FAMILY L)

The problem is, that in generated HTML the data-itemindex of hidden input is always "0" for the radios in second datagrid (see below). Interesting thing is, that the #{insuranceVar} is resolved in second datagrid only before the p:radioButton, as you can see on screenshot (see below).

HTML output:

Code: Select all

HTML from first datagrid:

<div id="testForm:j_idt145" class="ui-datagrid ui-widget">
  <div id="testForm:j_idt145_content" class="ui-datagrid-content ui-widget-content">
    <table class="ui-datagrid-data">
      <tbody>
        <tr class="ui-datagrid-row">
          <td class="ui-datagrid-column">CLASSIC S
            <div id="testForm:j_idt145:0:j_idt151" class="ui-radiobutton ui-widget">
              <div class="ui-helper-hidden-accessible">
                <input id="testForm:select1:0_clone" name="testForm:select1" type="radio" class="ui-radio-clone" data-itemindex="0" value=""></div>
                <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
                  <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
                </div>
              </div>CLASSIC S, iteration 0</td>
            <td class="ui-datagrid-column">CLASSIC FAMILY S
              <div id="testForm:j_idt145:1:j_idt151" class="ui-radiobutton ui-widget">
                <div class="ui-helper-hidden-accessible">
                  <input id="testForm:select1:1_clone" name="testForm:select1" type="radio" class="ui-radio-clone" data-itemindex="1" value=""></div>
                  <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
                    <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
                  </div>
                </div>CLASSIC FAMILY S, iteration 1</td>
              <td class="ui-datagrid-column">EXTRA S
                <div id="testForm:j_idt145:2:j_idt151" class="ui-radiobutton ui-widget">
                  <div class="ui-helper-hidden-accessible">
                    <input id="testForm:select1:2_clone" name="testForm:select1" type="radio" class="ui-radio-clone" data-itemindex="2" value=""></div>
                    <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
                      <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
                    </div>
                  </div>EXTRA S, iteration 2</td>
                <td class="ui-datagrid-column">EXTRA FAMILY S
                  <div id="testForm:j_idt145:3:j_idt151" class="ui-radiobutton ui-widget">
                    <div class="ui-helper-hidden-accessible">
                      <input id="testForm:select1:3_clone" name="testForm:select1" type="radio" class="ui-radio-clone" data-itemindex="3" value=""></div>
                      <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
                        <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
                      </div>
                    </div>EXTRA FAMILY S, iteration 3</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>
        
HTML from second datagrid: 

<div id="testForm:j_idt230" class="ui-datagrid ui-widget">
  <div id="testForm:j_idt230_content" class="ui-datagrid-content ui-widget-content">
    <table class="ui-datagrid-data">
      <tbody>
        <tr class="ui-datagrid-row">
          <td class="ui-datagrid-column">CLASSIC L
            <div id="testForm:j_idt230:0:j_idt300" class="ui-radiobutton ui-widget">
              <div class="ui-helper-hidden-accessible">
                <input id="testForm:select2:0_clone" name="testForm:select2" type="radio" class="ui-radio-clone" data-itemindex="0" value=""></div>
                <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
                  <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
                </div>
              </div>, iteration</td>
            <td class="ui-datagrid-column">CLASSIC FAMILY L
              <div id="testForm:j_idt230:1:j_idt300" class="ui-radiobutton ui-widget">
                <div class="ui-helper-hidden-accessible">
                  <input id="testForm:select2:1_clone" name="testForm:select2" type="radio" class="ui-radio-clone" data-itemindex="0" value=""></div>
                  <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
                    <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
                  </div>
                </div>, iteration</td>
              <td class="ui-datagrid-column">EXTRA L
                <div id="testForm:j_idt230:2:j_idt300" class="ui-radiobutton ui-widget">
                  <div class="ui-helper-hidden-accessible">
                    <input id="testForm:select2:2_clone" name="testForm:select2" type="radio" class="ui-radio-clone" data-itemindex="0" value=""></div>
                    <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
                      <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
                    </div>
                  </div>, iteration</td>
                <td class="ui-datagrid-column">EXTRA FAMILY L
                  <div id="testForm:j_idt230:3:j_idt300" class="ui-radiobutton ui-widget">
                    <div class="ui-helper-hidden-accessible">
                      <input id="testForm:select2:3_clone" name="testForm:select2" type="radio" class="ui-radio-clone" data-itemindex="0" value=""></div>
                      <div class="ui-radiobutton-box ui-widget ui-corner-all ui-state-default">
                        <span class="ui-radiobutton-icon ui-icon ui-icon-blank ui-c"></span>
                      </div>
                    </div>, iteration</td>
                </tr>
              </tbody>
            </table>
          </div>
        </div>

Screenshot:
Image

When I refactor this code to use ui:repeat, it works:

Code: Select all

<p:selectOneRadio id="select1" value="#{testModel.selectedText1}" layout="custom" >
  <f:selectItems value="#{testModel.texts1}" />
</p:selectOneRadio>

<ui:repeat var="insuranceVar" value="#{testModel.texts1}" varStatus="status">
  <p:panel>
    <h:outputText value="#{insuranceVar}"/>
    <p:radioButton for="testForm:select1" itemIndex="#{status.index}"/>
    <h:outputText value="#{insuranceVar}"/>
    <h:outputText value=", iteration #{status.index}"/>
  </p:panel>       
</ui:repeat>

<p:selectOneRadio id="select2" value="#{testModel.selectedText2}" layout="custom">
  <f:selectItems value="#{testModel.texts2}" />
</p:selectOneRadio>

<ui:repeat var="insuranceVar" value="#{testModel.texts2}" varStatus="status">
  <p:panel>
    <h:outputText value="#{insuranceVar}"/>  
    <p:radioButton for="testForm:select2" itemIndex="#{status.index}"/>
    <h:outputText value="#{insuranceVar}"/>
    <h:outputText value=", iteration #{status.index}"/>
  </p:panel>
</ui:repeat>
Image (vertical orientation in this case)

Observations:
  • I tried also p:dataTable and h:datatable with a same result as with p:dataGrid (not working properly)
  • When i comment out the p:radioButton inside dataGrid, then the second <h:outputText value="#{insuranceVar}"/> prints value as well as <h:outputText value=", iteration #{status.index}"/> :
    Image
  • When I change rowIndexVar and insuranceVar identifiers to be unique, it starts working (I cannot do this in real world - the p:selectOneRadio with p:dataGrid is supposed to be included via ui:include multiple times in the page)
Do you have any idea why this behaves so strange?

Thank in advance you for your time!
Martin


Primefaces version: 6.1.2 (tested with 6.2-SNAPSHOT too)
JSF version: Mojarra 2.2.13
Server: Tomcat v8
Last edited by csd1 on 27 Jun 2017, 12:06, edited 1 time in total.

csd1
Posts: 13
Joined: 31 Aug 2015, 15:35

26 Jun 2017, 13:33

I tried to use p:selectManyCheckbox with layout="custom" in the same use-case using panelgrid and it does not work as expected either.

Code: Select all

<p:selectManyCheckbox id="select1" value="#{testModel.selectedTexts1}" layout="custom">
  <f:selectItems value="#{testModel.texts1}" />
</p:selectManyCheckbox>

<p:dataGrid id="dataGrid1" value="#{testModel.texts1}" columns="4" rowIndexVar="index" var="insuranceVar">
    <h:outputText value="#{insuranceVar}"/> <!-- This prints out correnct value -->
    <h:outputText value=", iteration #{index}"/> <!-- This prints out correnct index -->
    <p:checkbox id="radio1" for="testForm:select1" itemIndex="#{index}"/> <!-- Here something goes wrong -->
    <h:outputText value="#{insuranceVar}"/> <!-- This does not print insuranceVar -->
    <h:outputText value=", iteration #{index}"/> <!-- This does not print index -->      
</p:dataGrid>

<p:selectManyCheckbox id="select2" value="#{testModel.selectedTexts2}" layout="custom">
  <f:selectItems value="#{testModel.texts2}" />
</p:selectManyCheckbox>

<p:dataGrid id="dataGrid2" value="#{testModel.texts2}" columns="4" rowIndexVar="index" var="insuranceVar">
  <h:outputText value="#{insuranceVar}"/> <!-- This prints out correnct value -->
  <h:outputText value=", iteration #{index}"/>  <!-- This prints out correnct index -->
  <p:checkbox id="radio2" for="testForm:select2" itemIndex="#{index}"/> <!-- Here something goes wrong -->
  <h:outputText value="#{insuranceVar}"/> <!-- This does not print insuranceVar -->
  <h:outputText value=", iteration #{index}"/> <!-- This does not print index -->
</p:dataGrid>
I'm tying to debug it that happens here, but without success...

csd1
Posts: 13
Joined: 31 Aug 2015, 15:35

27 Jun 2017, 08:04

I found out, that the issue occurs when a primefaces component with for attribute is used inside component that extends UIData (which is used multiple times on page with the same names for ''rowIndexVar" and "var"), like one of:
  • <p:radioButton id="radio2" for="testForm:select2" itemIndex="#{index}"/>
  • <p:checkbox id="radio1" for="form:select1" itemIndex="#{index}"/>
  • <p:outputLabel for="form:select1" value="label" />
  • <p:message for="form:select2" />
Tested it with MyFaces 2.2.12 and it behaves the same.

tandraschko
PrimeFaces Core Developer
Posts: 3979
Joined: 03 Dec 2010, 14:11
Location: Bavaria, DE
Contact:

27 Jun 2017, 08:57

I just tried a simple case within the showcase (i just modified the DataGridView to only create 3 cars...) and i cant see anything thats wrong:

Code: Select all

        <h:form>

            Value "#{autoCompleteView.txt1}"

            <p:selectOneRadio id="select1" value="#{autoCompleteView.txt1}" layout="custom" >
                <f:selectItem itemLabel="Red" itemValue="Red" />
                <f:selectItem itemLabel="Green" itemValue="Green" />
                <f:selectItem itemLabel="Blue" itemValue="Blue" />
            </p:selectOneRadio>

            <p:dataGrid value="#{dataGridView.cars}" columns="4" rowIndexVar="carIndex" var="car">
                <h:outputText value="#{car.id}"/>
                <p:radioButton for="@form:select1" itemIndex="#{carIndex}"/>
                <h:outputText value="#{carIndex}"/>
            </p:dataGrid>


            Value "#{autoCompleteView.txt2}"

            <p:selectOneRadio id="select2" value="#{autoCompleteView.txt2}" layout="custom" >
                <f:selectItem itemLabel="Red" itemValue="Red" />
                <f:selectItem itemLabel="Green" itemValue="Green" />
                <f:selectItem itemLabel="Blue" itemValue="Blue" />
            </p:selectOneRadio>

            <p:dataGrid value="#{dataGridView.cars}" columns="4" rowIndexVar="carIndex" var="car">
                <h:outputText value="#{car.id}"/>
                <p:radioButton for="@form:select2" itemIndex="#{carIndex}"/>
                <h:outputText value="#{carIndex}"/>
            </p:dataGrid>

            <p:commandButton update="@form" process="@form" value="Post" />
        </h:form>



JFYI: it's always good to provide examples based on the showcase, otherwise we may not able to help you.
Thomas Andraschko

PrimeFaces | PrimeFaces Extensions

Apache Member | OpenWebBeans, DeltaSpike, MyFaces, BVal, TomEE

Sponsor me: https://github.com/sponsors/tandraschko
Blog: http://tandraschko.blogspot.de/
Twitter: https://twitter.com/TAndraschko

csd1
Posts: 13
Joined: 31 Aug 2015, 15:35

27 Jun 2017, 11:01

Thank you for the suggestion to use Showcase to demonstrate the problem. I used your code and tried to change things. Finally I changed form id to "testForm" and expression in for attribute to "testForm:select1" and "testForm:select2" like this:

Code: Select all

<h:form id="testForm">

    Value "#{autoCompleteView.txt1}"

    <p:selectOneRadio id="select1" value="#{autoCompleteView.txt1}" layout="custom" >
        <f:selectItem itemLabel="Red" itemValue="Red" />
        <f:selectItem itemLabel="Green" itemValue="Green" />
        <f:selectItem itemLabel="Blue" itemValue="Blue" />
    </p:selectOneRadio>

    <p:dataGrid value="#{dataGridView.cars}" columns="4" rowIndexVar="carIndex" var="car">
        <h:outputText value="#{car.id}"/>
        <p:radioButton for="testForm:select1" itemIndex="#{carIndex}"/>
        <h:outputText value="#{carIndex}"/>
    </p:dataGrid>


    Value "#{autoCompleteView.txt2}"

    <p:selectOneRadio id="select2" value="#{autoCompleteView.txt2}" layout="custom" >
        <f:selectItem itemLabel="Red" itemValue="Red" />
        <f:selectItem itemLabel="Green" itemValue="Green" />
        <f:selectItem itemLabel="Blue" itemValue="Blue" />
    </p:selectOneRadio>

    <p:dataGrid value="#{dataGridView.cars}" columns="4" rowIndexVar="carIndex" var="car">
        <h:outputText value="#{car.id}"/>
        <p:radioButton for="testForm:select2" itemIndex="#{carIndex}"/>
        <h:outputText value="#{carIndex}"/>
    </p:dataGrid>

    <p:commandButton update="@form" process="@form" value="Post" />
</h:form>

and it does not work as expected.

tandraschko
PrimeFaces Core Developer
Posts: 3979
Joined: 03 Dec 2010, 14:11
Location: Bavaria, DE
Contact:

27 Jun 2017, 11:34

if you would like to use the id, you must use a absolut expression if you are inside a UIData component.
So this should work:
<p:radioButton for=":testForm:select1" itemIndex="#{carIndex}"/>

There are some articles about using search expression in stackoverflow, just search.
Thomas Andraschko

PrimeFaces | PrimeFaces Extensions

Apache Member | OpenWebBeans, DeltaSpike, MyFaces, BVal, TomEE

Sponsor me: https://github.com/sponsors/tandraschko
Blog: http://tandraschko.blogspot.de/
Twitter: https://twitter.com/TAndraschko

csd1
Posts: 13
Joined: 31 Aug 2015, 15:35

27 Jun 2017, 11:59

Thank you Thomas! I didn't expect it to be that simple :)

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: Victorxpi and 57 guests