JSF 2 ui:repeat vs h:datatable behavior - jsf-2

I had a bad time trying to solve p:selectBooleanButton doesn't render preselected value, a lot of hours just to fix it changing ui:repeat to h:datatable.
Here is both pieces of code.
<ui:repeat value="#{presupuestoBean.getItemsPresupuestBySeccion('Parte Delantera')}" var="itemPresupuesto">
<tr>
<td><h:outputText value="#{itemPresupuesto.descripcion}"/></td>
<td>
<p:selectBooleanButton value="#{presupuestoBean.itemsPresupuestoAsignadoCambiar[itemPresupuesto.id]}" onLabel="Yes" offLabel="No" onIcon="ui-icon-check" offIcon="ui-icon-close"/>
<h:outputText value="#{presupuestoBean.itemsPresupuestoAsignadoCambiar[itemPresupuesto.id]}" />
</td>
</tr>
</ui:repeat>
(Notice that the button is showing 'FALSE (or NO)' value although the property value is 'TRUE' as displayed by outputText)
On the other hand, the exactly same code with h:datatable.
<h:dataTable value="#{presupuestoBean.getItemsPresupuestBySeccion('Parte Delantera')}" var="itemPresupuesto2">
<h:column>
<h:outputText value="#{itemPresupuesto2.descripcion}"/>
</h:column>
<h:column>
<p:selectBooleanButton value="#{presupuestoBean.itemsPresupuestoAsignadoCambiar[itemPresupuesto2.id]}" onLabel="Si" offLabel="No" onIcon="ui-icon-check" offIcon="ui-icon-close"/>
<h:outputText value="#{presupuestoBean.itemsPresupuestoAsignadoCambiar[itemPresupuesto2.id]}" />
</h:column>
</h:dataTable>
Anyone know why is this happening ??. As far as I know, this two tags could be exchangeable. (at least according the example that I saw e.g JSF 2 Repeat Tag Example)
I'm using com.sun.faces jsf-api and jsf-impl 2.2.4
Also Primefaces 4.0

You confuse view build time with view render time! BalusC posted an explanation here:
JSTL in JSF2 Facelets... makes sense?

I had the same behavior, and was not able to make work the ui:repeat properly with map and default value.
As you are using primefaces, you might also found p:dataGrid as an alternative to h:dataTable.

Related

p:dataExporter does not keep the sorting of p:dataTable

The problem can be reproduced in PrimeFaces showcase:
http://www.primefaces.org/showcase/ui/data/dataexporter/basic.xhtml
<f:facet name="{Exporters}">
<h:commandLink>
<p:graphicImage name="/demo/images/excel.png" width="24"/>
<p:dataExporter type="xls" target="tbl" fileName="cars" />
</h:commandLink>
</f:facet>
I have no idea from where the export gets the sorting that it is using.
Is there any way to make p:dataExporter to keep the same order as in p:dataTable?
Edit: My client noticed that if you click a column to sort the datatable then export keeps the sorting. That's good but how to keep the initial sorting?

Replace <c:if> and fn:toUpperCase() with JSF-tags

This example is from a book on JSF. The excercise is to refactor the following Facelets code while eliminating <c:if> and fn:toUpperCase(). Usage of <c:forEach> is allowed.
#{myBean.numbers} returns String["one","two","three"]
As the book is on JSF and not on Java, I suppose the existing Java-code is not to be touched. But I can't think of another way to do this solely in Facelets.
<c:forEach var="item" items="#{myBean.numbers}">
<c:if test="#{not fn:endsWith(item,'o')}">
#{item}
</c:if>
<c:if test="#{fn:endsWith(item,'o')}">
#{fn:toUpperCase(item)}
</c:if>
</c:forEach>
Only thing I can think of is using a converter that conditionally uses String#toUpperCase() and then I still do not understand why use of <c:forEach> should still be allowed:
<ui:repeat var="item" value="#{myBean.numbers}">
<h:outputText value="#{item}" converter="conditionalConverter"/>
</ui:repeat>
Is there a more "Facelets way" to do this (and still a need to use <c:forEach>)?
UPDATE:
Instead of <c:if> one could still use e.g. <h:outputPanel> and it's rendered-attribute, but there is still no Java-less replacement for fn:toUpperCase().
I am asking for learning purposes only. I suppose the <ui:repeat>-solution with a converter is the cleanest and represents most how JSF is supposed to be used. Do you think so, too?
As to <c:if>, the JSF alternative to JSTL <c:if> is the rendered attribute on any component. For example, <h:panelGroup> or <h:outputText>. Those components doesn't generate additional markup if there are no attribtues specified which should end up in HTML, like id or styleClass, otherwise they generate a <span>.
Here's an example of both:
<h:panelGroup rendered="#{not fn:endsWith(item,'o')}">
#{item}
</h:panelGroup>
<h:outputText value="#{fn:toUpperCase(item)}" rendered="#{fn:endsWith(item,'o')}" />
As to fn:toUpperCase(), JSF has no alternative. I'm not sure why you would need a JSF alternative as it's essentially not a tag, but a simple EL function which is perfectly usable in both JSTL and JSF tags. In any case, you could if necessary throw in CSS text-transform: uppercase. As this takes place entirely client side, your only problem may be the browser support.
<h:outputText value="#{item}" style="text-transform: uppercase" />
(note: this is just an example, the normal practice is to put styles in its own .css file which you load by <h:outputStylesheet>)
<h:outputText value="#{item}" styleClass="uppercased" />
I suppose the -solution with a converter is the cleanest and represents most how JSF is supposed to be used. Do you think so, too?
I'm a big fan of "Use the right tool for the job". Use JSTL tags to conditionally build the JSF component tree. Use JSF components to generate HTML. That's it. See also JSTL in JSF2 Facelets... makes sense?

EL on DataTable Footer not showing

I'm working with a DataTable, and I'm having some trouble displaying a value from an EL in the footer. I have made a simplified version of my xhtml that still reproduces the error.
If I do the p:dataTable like this it all works:
<p:dataTable value="#{myMB.items}" var="item">
<p:column headerText="Value" footerText="Value">
<h:outputText value="#{item.value}">
<f:convertNumber pattern="###,##0.00"/>
</h:outputText>
</p:column>
</p:dataTable>
I get this as a result:
The footer shows just fine. And then I try it with EL, changing the column definition like this:
<p:column headerText="Value" footerText="#{3 + 11}">
<h:outputText value="#{item.value}">
<f:convertNumber pattern="###,##0.00"/>
</h:outputText>
</p:column>
And it evaluates my expression, I get this as a result:
It shows the correct value 14 in the footer. But when I try to use a value from my model, it doesn't show. See the example:
Code:
<p:column headerText="Value" footerText="#{item.value}">
<h:outputText value="#{item.value}">
<f:convertNumber pattern="###,##0.00"/>
</h:outputText>
</p:column>
Output:
And I have tried to do the footer in different ways. Not a single attempt worked.
Is there a correct way to do this? In the showcase it seems to work just fine.
I am using PrimeFaces 3.3.1
The problem was lack of attention.
I failed to realize that I have multiple column values for a single footer. And since JSF can't decide on a single value, it shows nothing.
Shortly after I posted this the answer came to me. I tried to define a single value on my ManagedBean to use as footer, and it work just fine.
Again, there's nothing wrong with JSF and/or PrimeFaces, it was just lack of logical thinking from my part.
It works on the showcase, because it shows subtables that actually do have a footer for each value.

How can I set numbers within IDs dynamically in JSF

I design a JavaEE website with the help of JSF2 and Facelets. The code beyond is just an example how the JSF-Code looks like.
When the user of the website wants to create new users but forgets to set e.g. the firstname, an error occurs and the element will be highlighted (red color and red frame around the element).
For highlighting I have to use the attribute:
class="#{faceletUtils.getLabelStyleClass('createUsersForm:allUsers:0:firstName')}"
The problem is that I have to set the number 0 dynamically but as far as I know nesting is not allowed in JSF. I could use #{curUser.number} to get the number.
Question: How can I set the numbers in the for and class attributes?
for="createUsersForm:allUsers:0:firstName"
class="#{faceletUtils.getLabelStyleClass('createUsersForm:allUsers:0:firstName')}"
An example of the JSF-Code:
<h:form id="createUsersForm">
<ui:repeat id="allUsers" value="#{createUserController.users}" var="curUser">
<div class="formLine">
<label for="createUsersForm:allUsers:0:firstName" class="#{faceletUtils.getLabelStyleClass('createUsersForm:allUsers:0:firstName')}">
<h:outputText value="#{userStaticText['user.firstName.label']}"/>
</label>
<h:inputText id="firstName" value="#{curUser.firstName}" class="#{faceletUtils.getLabelStyleClass('createUsersForm:allUsers:0:firstName')}"/>
</div>
</ui:repeat>
</h:form>
Best regards,
Jana
Just use <h:outputLabel> instead of <label>. JSF will automatically use the right for value. Further you can use #{component.clientId} to get the client ID of the current component (although I think the particular functional requirement of highlighting invalid fields can be solved in a much simpler manner).
<h:form id="createUsersForm">
<ui:repeat id="allUsers" value="#{createUserController.users}" var="curUser">
<div class="formLine">
<h:outputLabel for="firstName" styleClass="#{faceletUtils.getLabelStyleClass(component.clientId)}"
value="#{userStaticText['user.firstName.label']}"/>
<h:inputText id="firstName" value="#{curUser.firstName}" styleClass="#{faceletUtils.getLabelStyleClass(component.clientId)}"/>
</div>
</ui:repeat>
</h:form>
Note that I fixed the wrong class attribute of <h:inputText> as well.

how to render selected checkbox value in jsf when i select checkbox

i have renderd checkboxes. when i select checkbox that checkbox value shoud be displayed in panel.i have written code for this but not worked
<h:selectManyCheckbox id="chkedition" value="#{newspaperBean.selectedEditions}" layout="lineDirection" styleClass="nostyle">
<f:selectItems value="#{newspaperBean.searchEditionByNewspaper()}" var="item" itemLabel="#{item.editionName}" itemValue="#{item.editionName}"/>
<f:ajax render="display" event="select"/>
</h:selectManyCheckbox>
</td>
</tr>
<tr>
<td colspan="2">
<p:panel id="display" header="You have selected">
<c:forEach items="#{newspaperBean.selectedEditions}" var="it">
<h:outputText value="#{it}"/><br/>
</c:forEach>
</p:panel>
</td>
</tr>
this worked when i submit form but i want that when i select checkbox.
Remove the event="select" attribute. This is the incorrect event to hook on. It's only triggered when you select any text in input fields and textareas, not when you click the checkbox.
<f:ajax render="display" />
The default event is already valueChange which will resolve to click in checkboxes and this is exactly what you need. You can if necessary explicitly specify it by event="click", but as said, it's the default value already, so just omit it.
Another potential problem is the <c:forEach> in the panel. This will fail if the bean is view scoped because it runs during view build time and get its own separate instance of the view scoped bean which may not contain the submitted data. You'd need to use <ui:repeat> instead.
<ui:repeat value="#{newspaperBean.selectedEditions}" var="it">
<h:outputText value="#{it}"/><br/>
</ui:repeat>
See also:
JSTL in JSF2 Facelets... makes sense?

Resources