How can I show my 2D arrayList using the <ui:repeat> in JSF - jsf

I can show the objects of the plain arrayList.
ArrayList<Object>names;
<ui:repeat value="#{bean.names}" var="t">
<ul>
<li render="" id="hm">
<a>#{t.name}</a>
</li>
</ul></ui:repeat>
But if I have List<ArrayList<Object>> names2 = new ArrayList<ArrayList<Object>>();
I tried to use nested <ui:repeat> or <c:forEach> but it doesn't work. I dont want to use data tables since I want to display them as a list.
E.g I tried to do this but it doesn't work, neither with <ui:repeat>, is it possible what I try to do?
<ul>
<li>
<c:forEach items="#{bean.names2}" var="row">
<c:forEach items="#{row}" var="nested_row">
<c:forEach items="#{nested_row}" var="t">
<a>#{t.name}</a>
</c:forEach>
</c:forEach>
</c:forEach>
</li>
</ul>

Your code attempt with three <c:forEach>s expects a 3D array/list. Get rid of that one <c:forEach> too much.
<c:forEach items="#{bean.names2}" var="row">
<c:forEach items="#{row}" var="nested_row">
#{nested_row.name}
</c:forEach>
</c:forEach>
The same should work for <ui:repeat>.

Related

Use ui:repeat variable in c:if statement [duplicate]

This question already has an answer here:
Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work
(1 answer)
Closed 7 years ago.
I am trying to use a c:if statement inside a ui:repeat tag.
However U cannot get the value of course.days while inside the if tag. It just always evaluates to empty.
<div id="schedule_wrapper">
<ui:repeat value="#{schedule.courses}" var="course">
<div class="course">
<b>#{course.shortTitle}</b> : #{course.subjectCode} #{course.courseNumber}-#{course.section}<br />
#{course.roomCode} #{course.buildingName} <br />
<c:if test="${not empty course.days}">
#{course.days} : #{course.startTime} - #{course.endTime}
</c:if>
</div>
</ui:repeat>
</div>
Any ideas how I can use the course.days variable inside the if statement?
Or an alternate way to achieve the same thing...
All of the other course.xxxxx value as pulling their values in.
Try to use inside your using a rendered to check your condition.
rendered="#{not empty course.days}" or #{course.days > 0} if days is a Integer
<div id="schedule_wrapper">
<ui:repeat value="#{schedule.courses}" var="course">
<div class="course">
<b>#{course.shortTitle}</b> : #{course.subjectCode} #{course.courseNumber}-#{course.section}<br />
#{course.roomCode} #{course.buildingName} <br />
**<ui:fragment rendered="#{not empty course.days}">
#{course.days} : #{course.startTime} - #{course.endTime}
</ui:fragment>**
</div>
</ui:repeat>
</div>
I found an alternate way to achieve this.
Instead of:
<c:if test="${not empty course.days}">
#{course.days} : #{course.startTime} - #{course.endTime}
</c:if>
I used:
<h:panelGroup rendered="#{not empty course.days}">
#{course.days} : #{course.startTime} - #{course.endTime}
</h:panelGroup>
I am still interested if this is possible with an if statement.

Variable set by ui:param or c:set inside ui:repeat is not available outside ui:repeat

I would like to define a variable and reuse it somewhere else on the page. I'm defining variable in JSF using <ui:param> and <c:set> and resetting it in the <ui:repeat> depending on condition as follows:
<ui:param name="title" value="default value"/>
<c:set var="title2" value="default val"/>
<ui:repeat value="#{aClip.revisions}" var="revs" varStatus="revStat">
<ui:repeat value="#{revs.metadataMap.entry}" var="entryLst">
<ui:repeat value="#{entryLst}" var="entry">
<ui:repeat value="#{entry.value}" var="metaVal">
<ui:repeat value="#{metaVal.values}" var="aValue">
<ui:fragment rendered="#{metaVal.key eq 'Title'}">
rendered //this prints. condition is evaluted to true
<ui:param name="title" value="#{aValue}"/>
<c:set var="title2" value="#{aValue}"/>
title2 -- #{title2} title -- #{title} //prints
</ui:fragment>
</ui:repeat>
</ui:repeat>
</ui:repeat>
</ui:repeat>
</ui:repeat>
title2 -- #{title2} title -- #{title} //does not print value not even defualt val
I know condition is true and value is set, but when I try to use it outside loop, it doesn't evalute. It doesn't even evalute to defualt value given to variable while defining.
How is this caused and how can I solve it?

Handling a ui:repeat that returns empy value

I have a ui:repeat that returns a list of entity. Is there any way to know that the returned list is empty?
<ui:repeat id="resulta" value="#{testController.testList}" var="list">
<div>list.name</div>
</ui:repeat>
something like if ui:repeat is empty then display a div saying "List is empty"
i've heard about varStatus -> Facelets repeat Tag Index
but i don't think there is something for empty list. or is there?
UPDATED
<ui:repeat id="resulta" value="#{testController.testList}" var="list">
<div>list.name</div>
<h:panelGroup rendered="#{empty list}">
list is empty!
</h:panelGroup>
</ui:repeat>
I tried to render the "list is empty!" when the list is empty but then it doesn't show.
<ui:repeat id="resulta"
value="#{testController.testList}"
var="list">
<div>
#{list.name}
</div>
</ui:repeat>
<h:panelGroup rendered="#{empty testController.testList}">
List is empty!
</h:panelGroup>
rendered is a conditional statement which only if it is true renders. In case you want to render the last h:panelGroup as a div instead of a span, consider adding layout='block' to the element.
You can display your empty list message outside your <ui:repeat> element as:
<ui:repeat id="resulta"
value="#{testController.testList}"
var="list"
rendered="#{not empty testController.testList}">
<div>
#{list.name}
</div>
</ui:repeat>
<h:panelGroup rendered="#{empty testController.testList}">
list is empty!
</h:panelGroup>

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}" />

JSF: logic based on iteration index

Pardon me for the title, that's the best my limited brain can came up this late.
So, i have a list of string, something like [abc, def, ghi].
The question: in JSF, how do I iterate the list and create a string that look like this "abc, def, ghi" (notice the commas)?
For those who have the urge to tell me that I'd better use a Java method to concatenate the string, hear this: every member of the list should be rendered as a separate commandLink.
If plain JSF it would look like:
<h:commandLink>abc</h:commandLink>, <h:commandLink>def</h:commandLink>, <h:commandLink>ghi</h:commandLink>
Assuming that #{bean.items} returns List<String> or String[], in JSF 1.x you can use JSTL c:forEach with varStatus. It gives you a handle to LoopTagStatus which has a isLast() method.
<c:forEach items="#{bean.items}" var="item" varStatus="loop">
<h:commandLink value="#{item}" /><c:if test="#{!loop.last}">, </c:if>
</c:forEach>
In Facelets as shipped with JSF 2.x, same functionality is available by ui:repeat.
<ui:repeat value="#{bean.items}" var="item" varStatus="loop">
<h:commandLink value="#{item}" />#{!loop.last ? ', ' : ''}
</ui:repeat>

Resources