c:forEach - ui:include - dataTable issue - jsf

I have some code like:
<c:forEach>
<ui:param name="orderItemsList" value="#{appPortfolioBomBean.orderItemsByVdcMap[vdc.internalId]}" />
<ui:include>
....
</ui:include>
</c:forEach>
and the component I include contains a datable which renders some value based on orderItemsList parameter.
The problem is that the dataTable is rendered only for the LAST item from <c:forEach>...
Do you see what I am doing wrong? I am sure is something about jsf/jstl tags but cannot find out... I've tried to use ui:repeat instead of c:forEach but the same issue occurs

Try UI repeat instead
<ui:repeat value="${bean.list} var="variableName">
<!--YOUR CODE ->
</ui:repeat>

Solution found:
I'm using icefaces and for this specific issue they recommends:
Yes, I've seen the same problem with ui:repeat and dataTable.
Try to replace ui:repeat with <ice:panelSeries>.
Replaced and it works!

Related

How to do conditional update on a component

I have a JSF composite component which renders only some parts based on the attribute cc.attrs.list passed to it.
In one of the components I want to update a set of other components based on the attribute. So something like this:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{cc.attrs.id2}_resultTable"/>
The problem is that the resultTable is not rendered all the time and when the resultTable is not there, I get an exception Cannot find component with expression "id_resultTable", which is not surprising. So my idea was to create a variable which will contain id of the attribute or empty String like this:
<c:if test="#{cc.attrs.list}">
<ui:param name="updateTable" value="#{cc.attrs.id2}_resultTable"/>
</c:if>
<c:otherwise>
<ui:param name="updateTable" value=""/>
</c:otherwise>
and then do the ajax update like this:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{updateTable}"/>
The problem is, that the #{updateTable} variable is always an empty String(I've tried to put it as a content of outputText) and I have no idea why.
You can just omit the ui:param and do the check directly in the p:ajax:
<p:ajax event="dialogReturn" listener="#{cc.listener}"
update="#{cc.attrs.id2}_input #{cc.attrs.list ? cc.attrs.id2.concat('_resultTable') : ''}"/>
A problem with the c:if-approach could be, that when you update this section via ajax the condition is not re-checked as JSTL-tags are evaluated at view build time. Have a look at JSTL in JSF2 Facelets... makes sense? for further information.
This is not really a solution, but I've done a workaround for the problem which works. I've added h:panelGroup with id around the table and I'm updating this instead of the table.

JSF 2 ui:repeat h:form h:inputText

Iam iterate a list of objects with ui:repeat.
For each Object h:form, h:inputText (for order value) and the commandLink for adding the Item will be generated.
<ui:repeat var="article" value="#{someDataBean.myArrayList}">
<h:form>
Value: <h:inputText value="#{baskedBean.articleValue"} />
<h:commandLink value="add" action="#{baskedBean.addArticel(article)}" />
</h:form>
</ui:repeat>
Lets suppose we have only one article, the order value (baskedBean.articleValue) is submitted and setted correctly.
If we have more than one article in the ui:repeat value list, the submitted value isnt setted. Expect i use the last article.
It looks like, that the other h:inputText components (under the current) will overwrite the value (baskedBean.articleValue)
I tought, that i could handle the problem by sourrunding the related article h:input and commandLink components by a dedicated h:form (only for the article) but it didn't work.
Iam using mojarra 2.2.4 (and testet it also with 2.2.3)
thanks
thanks for your help

How get row index of <ace:dataTable> in every row?

In searching I found that we can do something with rowStateVar or rowIndex attributes of <ace:datatable>, but how?
I tried using <h:outputText value="#{myDataTableVar.rowIndex}"> but it shows an error message that myDataTableVar has no property rowIndex.
For a component library independent way, just use UIData#getRowIndex() as every component library specific datatable extends from this base component.
In the below example, x: can be anything: standard JSF h:, ICEfaces ice: or ace:, PrimeFaces p:, RichFaces rich:, etc.
<x:dataTable binding="#{table}" ...>
<x:column>#{table.rowIndex}</x:column>
</x:dataTable>
Note: the binding="#{table}" is as-is! You don't need to bind it to some managed bean property.
I found the solution <ace:datatable id='tbl' rowIndexVar="row"> and then just print like that <h:outputtext value="#{row}">Very simple
First, set varStatus:
<ice:dataTable varStatus="status">
An then, inside that dataTable, use:
#{status.index}

JSF Primefaces TabView problems

I asked this in the PF Forum but no one seems to want to answer so I though I'd try my luck here.
I have a ui:repeat that is not being updated correctly after an Ajax call when it is within a TabView.
Simple scenario is I have a ui:repeat pointing at an ArrayList (ArrayList contains simple pojos with a String). Within this I have an h:inputText whose value is the pojo's String getter/setter. The ui:repeat is contained within a h:panelGroup. I use a p:commandButton to run an action to update the ArrayList (just add a couple of objects to it a Math.random value for the String) and then update the h:panelGroup. The updated values in the ArrayList are not reflecting in the ui:repeat input fields. This only appears to be affecting input fields as outputText fields do update correctly. Also if I do the same for a p:dataTable the input field are updated correctly. If I remove the Tabview and Tab tags it works fine.
As it works when removing the Tabs I can only assume this is a bug and not designed to work like this. If someone could please confirm if this is so or if there is a viable work around. I need to use a ui:repeat as my fields are not in a tabular format. This has only occurred since migrating from PF 2.2. I'm currently on PF 3.1, Weblogic 10.3.4 and Mojarra 2.0.4
<p:tabView>
<p:tab title="Test">
<h:form prependId="false">
<p:commandButton id="testStringCheck"
value="Test String Check"
process="#form"
update="testPanel"
action="#{testBean.generateVOwithRandomStrings}">
</p:commandButton>
<h:panelGroup id="testPanel" layout="block">
<ui:repeat value="#{testBean.voList}" var="entry">
<h:outputText value="#{entry.randomString}"/>
<p:inputText style="display:block;"
value="#{entry.randomString}"
size="15">
</p:inputText>
</ui:repeat>
</h:panelGroup>
</h:form>
</p:tab>
</p:tabView>
As a workaround I've used a p:datagrid instead of a ui:repeat. This achieves the look I had in the the ui:repeat so I'm happy. Hopefully this bug will be fixed on future releases.
This is something of a bug in Primefaces commandButton. See the following thread:
http://forum.primefaces.org/viewtopic.php?f=3&t=17454
You can try replacing
<p:commandLink id="testStringCheck" ... update="#form" />
With an <h:commandLink>
<h:commandLink id="testStringCheck" render="#form"/>
Also from the above link here is an interesting method that somebody posted that enables you to correctly find the correct clientId to update.
http://paste.kde.org/177698/
temp solution: insert outside h:panelGroup:
<p:outputPanel defered="true" delay="1" ..>
and update outputPanel instead of panelGroup
Or use a datalist component instead of ui:repeat.
One more, i'm not sure but you can try, so update class instead id:
<h:panelGroup id="testPanel" layout="block" styleClass="testPanelCl" ../>
and update : #(.testPanelCl), don't forget id of panelGroup, without id JSF can not update by class

How to use ui:include inside a forEach and use the loop variable inside the included page?

I'm upgrading to JSF 2.0.2 inside Tomcat 7.0.12 and I have a page with a variable number of reusable widgets on it. I used to use t:aliasBean for this purpose, but it doesn't seem to work. I'm now trying the following in my Xhtml:
<c:forEach items="${viewBean.currentView.parts}" var="part">
<t:div styleClass="div#{viewBean.partNumber[part]}">
<c:forEach items="${part.widgets}" var="widget">
<f:subview id="div#{viewBean.widgetId[widget]}">
<ui:include src="widgets/#{widget.widgetPage}">
<ui:param name="widget" value="#{widget}" />
</ui:include>
</f:subview>
</c:forEach>
</t:div>
</c:forEach>
What seems to happen is the next widget from the loop is used in the previous widget's page, so I get errors unless there is only one widget.
Edit: I've tried ui:repeat - it doesn't work. I've also tried removing the ui:include, just as a sanity test; the looping works fine. Also, I'm using Spring 2.5.6.SEC01 - though it shouldn't matter.
I propose to use ui:repeat instead of c:forEach.
Why?
The most important thing to understand
about the jstl tags in Facelets is
that they do not represent components
and never become a part of the
component tree once the view has been
built. Rather, they are tags which are
actually responsible for building the
tree in the first place. Once they
have done their job they expire, are
no more, cease to be, etc etc.
Source [here][1]. I really recommend to read the entire article.
UPDATE:
Please note that I do not say that c:forEach is bad. I want to underline that mixing it with ui:repeat it's not recommended.
[1]: https://rogerkeays.com/jsf-c-foreach-vs-ui-repeat

Resources