Conditionally creating table rows JSF2 - jsf

I want to create a table which display a list of values in several rows, each row should contains only 3 columns.
I can create this by using JSTL but not using JSF. I am suspecting that it is xhtml related issue, not a problem in JSP, xhtml is very strict about the elements formation. Is there a way to achieve this?
Using JSTL:
<c:forEach var="book" value="${bookBean.bookList}" varStatus="bookStatus">
<c:if test="${bookStatus.index eq 0 or bookStatus.index mod 3 eq 0}">
<tr>
</c:if>
<td>
<table>
<tr>
<td>#{book.bookId}</td>
<td>#{book.bookName}</td>
<td>#{book.price}</td>
<td>#{book.author}</td>
</tr>
</table>
</td>
<c:if test="${bookStatus.count mod 3 eq 0}">
</tr>
</c:if>
</c:forEach>
Using JSF:
<ui:repeat var="book" value="#{bookBean.bookList}" varStatus="bookStatus">
<ui:fragment rendered="#{bookStatus.first or bookStatus.index mod 3 eq 0}">
<tr> <!-- Here i am getting an error saying closing tr missed.--->
</ui:fragment>
<td>
<table>
<tr>
<td>#{book.bookId}</td>
<td>#{book.bookName}</td>
<td>#{book.price}</td>
<td>#{book.author}</td>
</tr>
</table>
</td>
<ui:fragment rendered="#{(bookStatus.index+1) mod 3 eq 0}">
</tr>
</ui:fragment>
</ui:repeat>

This is actually not easy to do without using some component library (richfaces I know for a fact that has a component that does this.. rich:dataGrid..)
Here's a solution I found a while back to solve this issue... (I'm not a big fan of component libraries myself... ).. it's not the most elegant solution.. but it does the trick..
<table>
<tr>
<ui:repeat var="book" value="#{bookBean.bookList}" varStatus="bookStatus">
<td>
<table>
<tr>
<td>#{book.bookId}</td>
<td>#{book.bookName}</td>
<td>#{book.price}</td>
<td>#{book.author}</td>
</tr>
</table>
</td>
<h:outputText value="</tr><tr>" escape="false" rendered="#{(bookStatus.index + 1 ) mod 3 eq 0}"/>
</ui:repeat>
</tr>
</table>

As #FMQ has mentioned, try to use a JSF component library. Primefaces could be a good option, checkout the Demo page.

Related

Methods execute in wrong order

Methods in xhtml are supposed to run in hierarchical order.
cursoAlumnoView.listarEntrega() runs first, then all methods listed above it.
<c:forEach items="#{cursoAlumnoView.listaCursoAlumno()}" var="cur">
#{cursoAlumnoView.setIdusu(cur.idUsuario)}
<tr class="text-center">
<td>#{cur.idUsuario.idUsuario}</td>
<td>#{cur.idUsuario.nombres} #{cur.idUsuario.apellidos}</td>
<td>
#{cursoAlumnoView.devolverPromedioLista()}
</td>
<c:forEach items="#{cursoAlumnoView.listarEntrega()}" var="c">
<c:if test="#{c.nota lt 6}">
<td class="table-danger">
#{c.nota}
</td>
</c:if>
<c:if test="#{c.nota ge 6}">
<td class="table-success">
#{c.nota}
</td>
</c:if>
</c:forEach>
<c:if test="#{actividadView.listaCursoAsignatura().size() gt cur.idUsuario.entregaActividadCollection.size()}">
<c:forEach begin="1" end="#{actividadView.listaCursoAsignatura().size() - cur.idUsuario.entregaActividadCollection.size()}">
<td class="table-danger">0.0</td>
</c:forEach>
</c:if>
</tr>
</c:forEach>

How can I render another attribute from a p:dataTable of the same row (JSF)?

I am working with JSF 2.2 and Primefaces 6.0. I have a p:dataTable with different p:columns, and each column has many rows. I would like that, whenever column1 input changes, column2 input, in the same row, updates, however, it is not working; it doesn't render.
This is my xhtml code:
<p:dataTable value="#{myBean.objectsList}" var="object">
<p:column headerText="column1">
<table>
<tbody>
<ui:repeat value="#{object.subObjects}" var="object2">
<tr>
<td>
<c:set var="object3" value="#{object2.subObjects}"/>
<h:inputText id="value1#{myBean.toString(object3)}" value="#{object3.value1}">
<f:ajax event="change" listener="#{myBean.doSomething}"
execute="#this" render="#this"/>
</h:inputText>
</td>
</tr>
</ui:repeat>
</tbody>
</table>
</p:column>
<p:column headerText="column2">
<table>
<tbody>
<ui:repeat value="#{object.subObjects}" var="object2">
<tr>
<td>
<c:set var="object3" value="#{object2.subObjects}"/>
<h:inputText value="#{object3.value2}" disabled="disabled">
<f:ajax event="change" listener="#{myBean.doSomething2}"
execute="#this" render="value1#{myBean.toString(object3)}"/>
</h:inputText>
</td>
</tr>
</ui:repeat>
</tbody>
</table>
</p:column>
</p:dataTable>
Each object has many objects as a List.
In f:ajax tag of the first column (column1), you have given #this as value for the attribute render.
Instead, please try giving id of the component column2 or id of the p:dataTableitself.

Primefaces selectOne Radio button not working as required

I have a condition where i need to have two radio buttond with related data in the below the buttons.
i did something like below but the selected radio button value is not getting in the backed been. Please correct where i am going wrong
<table>
<tr>
<td>
<h:selectOneRadio value="#{beenObject.adressSelection}">
<f:selectItem itemValue="Employer" itemLabel="Employer" />
</h:selectOneRadio>.
</td>
<td>
<h:selectOneRadio value="#{beenObject.adressSelection}">
<f:selectItem itemValue="Consultant" itemLabel="Consultant" />
</h:selectOneRadio>.
</td>
</tr>
<tr>
<td>
<h:outputText value="#{beenObject.consultentDetailsString}">
</h:outputText>
</td>
</tr>
<tr>
<td>
<h:outputText value="#{beenObject.employerDetailsString}">
</h:outputText>
</td>
</tr>
</table>
I'm facing an issue similar as yours however I tried to replicate my situation at your code. While I was simplifying the lines I just end-up fixing your bug.
Below the code wich will work for you.
<table>
<tr>
<td>
<h:selectOneRadio value="#{beenObject.adressSelection}">
<f:selectItem itemValue="Employer" itemLabel="Employer" />
<f:selectItem itemValue="Consultant" itemLabel="Consultant" />
</h:selectOneRadio>
</td>
</tr>
<tr>
<td>
<h:outputText value="#{beenObject.consultentDetailsString}">
</h:outputText>
<h:outputText value="#{beenObject.employerDetailsString}">
</h:outputText>
</td>
</tr>
</table>
Explaining what I did:
I grouped the elements f:selectItem underneath f:selectItems like is shown in the sample at primeface showcase and it starts to work.
Hope it work as you want.
Cheers.

<p:row> renders incorrect result

I have been working on this problem from last two days. I went through the apis possibly I could refer to but no luck.
I have been using ui:repeat as jsf facelet to render data with rows and columns
Code for reference
<ui:repeat var="pendingRequestItem" value="#{oqHomeController.allRequests}" > --JSF
<p:row rendered="#{oqHomeController.renderPendingRequest}> -- PRIMEFACES FOR ROW
<td><h:outputText value="#{pendingRequestItem.title}" /></td>
<td><h:outputText value="#{oqHomeController.pendingCount}" /></td>
</p:row>
</ui:repeat>
And the above code is resulting in the following which is very strange.
<tbody>
<td>Request for Quote 1</td>
<td>1</td>
<td>DTHEME1</td>
<td>4</td>
</tbody>
I hope it should be
<tbody>
<tr>
<td>Request for Quote 1</td>
<td>1</td>
</tr>
<tr>
<td>DTHEME1</td>
<td>4</td>
</tr>
</tbody>
Please help thanks.
Have you tried <p:dataTable> it seems that is what you are looking for:
<p:dataTable var="pendingRequestItem" value="#{oqHomeController.allRequests}">
<p:column>
<h:outputText value="#{pendingRequestItem.title}"/>
</p:column>
<p:column>
<h:outputText value="#{oqHomeController.pendingCount}"/>
</p:column>
</p:dataTable>

Display values in JSF table

I have a Java object with 30 attributes. I populate the object from database. I want to display only values which are not empty.
<table>
<col width="280"/><col width="130"/>
<ui:repeat var="ud" value="#{TreeViewController.componentData}">
<tr>
<td>
<h:outputText value="componentStatsId" rendered="#{ud.componentStatsId != 0}"/>
</td>
<td>
<h:outputText value="#{ud.componentStatsId}" rendered="#{ud.componentStatsId != 0}"/>
</td>
</tr>
.......... and 40 more table rows
</ui:repeat>
</table>
I tested to create simple JSF table with rows which are not rendered if the values are empty. But I noticed that if the values are empty I get tiny spaces:
How I can solve this problem?
Yes, that would be the expected behavior from your code since is just preventing the rendering of the <<h:outputText> but not the <tr> nor <td> components.
To solve this, you should use <ui:fragment> and control the <tr> and <td> renderization using the rendered attribute:
<ui:repeat var="ud" value="#{TreeViewController.componentData}">
<ui:fragment rendered="#{ud.componentStatsId != 0}">
<tr>
<td>
componentStatsId
</td>
<td>
#{ud.componentStatsId}
</td>
</tr>
</ui:fragment>
<!-- .......... and 40 more table rows -->
<ui:fragment rendered="#{ud.componentTypeId != 0}">
<tr>
<td>
...
</td>
<td>
...
</td>
</tr>
</ui:fragment>
</ui:repeat>

Resources