Render child component when parent component rendered property is false? - jsf

I want to create a grid like this:
Element1 Element2 Element3
Element4 Element5 Element6
I have the following code:
<ui:repeat value=#{beans.myElementList} var="element" varStatus="i">
<b:row rendered=#{i.index%3==0}>
<b:column medium-screen="4">
#{element.display}
</b:column>
</b:row>
</ui:repeat>
The result of my code:
Element1
Element4
How to solve this problem?

<b:panelGrid> to the rescue:
<ui:repeat value=#{beans.myElementList} var="element">
<b:panelGrid columns="3" size="md">
#{element.display}
</b:panelGrid>
</ui:repeat>
<b:panelGrid> is inspired by the standard <h:panelGrid>, which renders an HTML table. Similarly, <b:panelGrid> renders a table consisting of Bootstrap rows and columns. Simply put everything you want to display into the panel grid. BootsFaces automatically detects when to render a new row.
The use case I originally had in mind is a form. More often than not, such a form is a repetition of identical lines: label, input field, error message. <b:panelGrid> allows you to create tabular forms like this with minimal effort.
Also see the documentation of <b:panelGrid>.
Addition until BootsFaces 1.2.0 is released:
Looking at the documentation, I wasn't happy what I saw. So I've corrected and updated it. Until BootsFaces 1.2.0 is released, also see the documentation of the developer showcase.

Try the below code.
The first ui:repeat renders <row> for each 3 elements, the second one renders elements (within <column>) in groups of 3 elements each.
<ui:repeat value="#{beans.myElementList}" step="3" varStatus="i" >
<b:row>
<ui:repeat value="#{beans.myElementList}" var="element"
step="1" offset="#{i.index}"
size="#{i.index + 3 le beans.myElementList.size() ? i.index + 3 : beans.myElementList.size() }"
varStatus="j" >
<b:column medium-screen="4">
#{element.display}
</b:column>
</ui:repeat>
</b:row>
</ui:repeat>

Related

How do I get h:outputText inside of a ui:repeat nested in h:dataTable to update when the datatable is updated?

So the relevant sections of my code is:
<h:panelGroup id="pnlGrp" style="padding:10px" width="100%">
<div>
<h:dataTable id="availableCrList"
value="#{searchData.availableCrList}"
var="avail"
varStatus="thisVarStatus" rows="#{searchData.rowsPerPage}"
sortColumn="#{searchData.crSortColumnName}"
sortAscending="#{searchData.crAscending}" style="width:100%;">
<h:column>
<ui:repeat value="#{avail.crRsnCdList}"
var="crRsnCd"
varStatus="status">
<h:outputText value="#{crRsnCd}<br />"
title="#{avail.crRsnDescList[status.index]}"
escape="false"/>
</ui:repeat>
</h:column>
</h:dataTable>
</div>
</h:panelGroup>
I'm working inside a legacy application and my goal is to display a list of codes which indicate reasons why a given item in this table might be completed, or cancelled, et cetera. The title is converted into a hovering tooltip which displays the description for each of these codes.
Now, I managed to get this working for singular codes no problem, but since switching from a String to a List of strings it's been a nightmare trying to get this to work.
Right now with the above code it displays the codes correctly the first time, but when I update the datatable by searching for a new value all the other columns (not shown) are correctly displayed while the RsnCd column continues to display the same data from the first search.
As an example, the first time I search for records the datatable might pull up:
Row1:A1
Row2:A1
Row3:A1
A3
Row4:A1
The second time I search for data I would expect to see only:
Row1:
Row2:
Row3:
Row4:
Row5:
Row6:
Row7:
But instead I get:
Row1:A1
Row2:A1
Row3:A1
A3
Row4:A1
Row5:
Row6:
Row7:
Really not sure if I'm explaining this adequately/understandably.
I solved this issue by changing
<ui:repeat value="#{avail.crRsnCdList}"
var="crRsnCd"
varStatus="status">
<h:outputText value="#{crRsnCd}<br />"
title="#{avail.crRsnDescList[status.index]}"
escape="false"/>
</ui:repeat>
To:
<ice:column>
<ice:repeat value="#{avail.crRsnCdList}"
varStatus="status">
<ice:outputText value="#{avail.crRsnCdList[status.index]}<br />"
title="#{avail.crRsnDescList[status.index]}"
escape="false"/>
</ice:repeat>
</ice:column>
I tried getting rid of the value but it stopped displaying anything.

Evaluation with <c:when> in data table doesn't work

I have searched and tried but this time I'm really stuck.
I am trying to build a simple datatable (primefaces) where the cell content can be of different types. There is a holder class for each cell content that can hold different entities and I want to use < c:choose> to check and display the right entity in the entity specific way.
The code looks like:
<p:dataTable emptyMessage="" value="#{date.getThreadContent(column.propertyID)}" var="content">
<p:column>
#{content.type}
<c:choose>
<c:when test="#{content.type == 'activity'}">
#{content.activity.name}
</c:when>
<c:when test="#{content.type == 'todo'}">
#{content.activity.name}
</c:when>
<c:otherwise>
Neither activity or todo
</c:otherwise>
</c:choose>
</p:column>
</p:dataTable>
The EL evaluation doesn't work regardless if I try a boolean or String values in the bean (I'm using String value in the code above).
So each time the content is not empty, the output first displays the correct content type from #{content.type} but then together with 'Neither activity or todo'.
I can also say that this data table itself represents a cell content in a parent data table (list of entities per date) that is not visible in this code as I try to isolate the problem.
Could it be that this type of expression cannot be done in a ?
Any help is appreciated.
Use JSF rendered tags to do your conditional display logic, it removes it from the DOM completely and makes validations easier.
Refer: http://docs.oracle.com/javaee/6/tutorial/doc/bnaik.html for EL expressions
Also a good explanation is provided by BalusC here: JSTL c:if doesn't work inside a JSF h:dataTable
<p:dataTable emptyMessage="" value="#{date.getThreadContent(column.propertyID)}" var="content">
<p:column>
#{content.type}
<h:outputText value="#{content.activity.name}" rendered="#{content.type == 'activity' or content.type == 'todo'}" />
<h:outputText value="Neither activity or todo" rendered="#{content.type != 'activity' and content.type != 'todo'}" />
</p:column>
</p:dataTable>

Generate output text from a list

I have a SEAM JSF web application with a Java back end. I have a list of objects who has a display value which I would like to display. Since the list is retrieved from the DB, it is dynamic
<s:decorate>
<ui:define name="label">Description:</ui:define>
<!-- foreach book in bookList -> display the description
<h:outputText value="#{bean.bookList.book.description}"/>
-->
</s:decorate>
So in a way I would like to create a sort of foreach loop for labels.
<ui:repeat value="#{bean.bookList}" var="book">
<h:outputText value="#{book.description}"/>
</ui:repeat>

jsf repeat inside datatable

I'm using datatable and i get number of columns dynamically. I tried to put repeat inside like this way:
<h:dataTable value="#{movieUserBean.sits}" var="row"
rowClasses="oddRows,evenRows" headerClass="header"
styleClass="table" cellpadding="5" cellspacing="0">
<ui:repeat value="#{row}" var="sit">
<h:column>
<h:selectBooleanCheckbox value= "#{movieUserBean.checked[sit.id]}"/>
</h:column>
</ui:repeat>
Which sits is a two dimensions array, my thought was that datatable should loop over the sits rows and repeat loops over every value inside every row (which is an object named Sit with get method: getId).
The problem is that I get an empty table. Seems like var "sit" is not getting value.
Can the problem be the fact that datatable ignores any elements who's not in column scope?
ui:repeat is called before the render response phase, i suggest you to use DynamicColumns of primefaces http://www.primefaces.org/showcase/ui/datatableDynamicColumns.jsf
A simple solution would be
<table>
<ui:repeat value="#{movieUserBean.sits}" var="row">
<tr>
<ui:repeat value="#{row}" var="sit">
<td><h:selectBooleanCheckbox value= "#{movieUserBean.checked[sit.id]}"/></td>
</ui:repeat>
</tr>
</ui:repeat>
</table>
If you have variable columns per row it might mess up with css styles. For example 5 columns on row one and 3 columns on row 2, how would you style them. The way i see it you want to show seats in a theater occupied with a checkbox.
You can try using ui:repeat's with ul,li or div's instead of going with the table. approach.

JSF 2 Composite Component rendering problem

My composite component (cc) creates an inputText-Field. The important part is, that it is rendered depending on the models property "visible". The model is given to the component via parm "name".
<cc:interface>
<cc:attribute name="name" required="true"/>
</cc:interface>
<cc:implementation componentType="ch.sbi.pt.components.PMSInputText">
<h:inputText value="#{cc.attrs.name.value}" rendered="#{cc.attrs.name.visible}"/>
</cc:implementation>
In the view i have a panelGrid with 2 cells/row: the first row has a label and my cc, the second is not important. The label renders itself with the same model-property as my cc does.
<h:panelGrid columns="2">
<h:outputText value="Name" rendered="#{person.name.visible}"/>
<sbic:pmsInputText name="#{person.name}"/>
<h:outputText value="Next Label"/>
<sbic:pmsInputText name="#{something.name}"/>
</h:panelGrid>
The result (and problem) is the following, if "visible"-property returns "false":
None of the components are rendered (perfect!) BUT the cc resulting HTML leaves an empty cell (e.g. <td></td>) which results in a ugly layouted HTML-Table (offset one cell):
<table>
<tbody>
<tr>
<td></td>
<td>Next Label</td>
</tr>
....
As far as I understand this has to do with the lifecycle (jstl vs. jsf): my cc renders before the <h:outputText../> but how can i get rid of the empty cell (e.g. <td></td>)? Am i missing something here?
Thanx for your help, experts!
Marc
This is fully expected. The composite component is rendered. Only its children are not. You need to move the rendered attribute to the composite component instead.
<sbic:pmsInputText name="#{person.name}" rendered="#{person.name.visible}" />

Resources