Generate output text from a list - jsf

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>

Related

Primefaces Diagram - Generating IDs for DOM Elements

I'm trying to create a <p:diagram> with elements which contain input fields, but the problem is that for each added element, the name and ID are the same for each input field.
What I've tried to do to give each field a unique id is adding a bean-generated ID for each element, but this just gets omitted in the final code. Here's my EL/xhtml:
<p:diagram value="#{Controller.model}" style="height:600px;width:1500px" styleClass="ui-widget-content" var="lrvEl" scrollable="true">
<f:facet name="element">
<div onmouseleave="nodeOnMouseOut(this)" onclick="nodeOnClick(this)">
<h:outputText value="#{lrvEl.title}" style="display:block;margin-top:1em;width:100%;height:10px;padding-left:4px"/>
<h:outputText value="#{lrvEl.description}" style="display:block;margin-top:1em;width:100%;height:10px;padding-left:4px"/>
<h:inputText id="inputEpValue_#{lrvEl.id}" name="inputEpValue_#{lrvEl.id}" onchange="setScoreVal('#{lrvEl.id}', this)" rendered="#{lrvEl.isScore()}" style="display:block;margin-top:1em;height:10px;padding-left:4px">
</h:inputText>
</div>
</f:facet>
<p:ajax event="connect" listener="#{Controller.onConnect}" />
<p:ajax event="disconnect" listener="#{Controller.onDisconnect}" />
<p:ajax event="connectionChange" listener="#{Controller.onConnectionChange}" />
</p:diagram>
The important bit here is the <h:inputText id='inputEpValue_#{lrvEl.id}' ... > - this comes out on the page as the following:
editor:LRVContent:overlayForm_lm:inputEpValue
as if the value wasn't set, however, as you can see in the onchange field I use the same constellation. This gets rendered as onchange="setScoreVal('ep:2', this)" so that works.
Can I not dynamically set IDs for elements in this fashion? Is there another way?
Edit:
The actual Reason I want to do this is that, if I have more than one input with the same generated ID, the focus(/cursor) will automatically jump into the last generated input field when I click on any one of them, meaning I won't be able to actually change the value of any of those fields.

Render child component when parent component rendered property is false?

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>

JSF h link takes last item in list instead of current

I got a list of objects displayed in a page.
This is the view:
<h:form>
<h:dataTable var="o" value="#{opleidingController.opleidingen}" border="0" >
<h:column>
<f:facet name="header">Code</f:facet>
<h:link value="#{o.opl_code}" outcome="#{opleidingController.getOpleidingByCode(o.opl_code)}" />
</h:column>
<h:column>
<f:facet name="header">Titel</f:facet>
<h:outputText value="#{o.opl_titel} "></h:outputText>
</h:column>
<h:column>
<f:facet name="header">Thema</f:facet>
<h:outputText value="#{o.opl_thema} "></h:outputText>
</h:column>
</h:dataTable>
</h:form>
This displays everything very well.
Like you can see I got the code part of the object set as a link.
With this code I get an object out of the database, from which I display the details.
The problem here is that every link displays the details of the last object of the list instead of the current object where I click the link.
This is the function I call (which works):
public String getOpleidingByCode(String code) {
this.opleiding = this.opleidingFacade.getOpleidingByCode(code);
return "details";
}
I hope any of this makes any sense?
Sorry if the solution is super clear but I am new to all of this.
Thanks in advance!
Kind regards
Deflandrex
EDIT:
This is the function that I use to call the first view (from which I provided the code)
public String getOpleidingenOpThema() {
this.opleidingen = this.opleidingFacade.getOpleidingenOpThema();
return "resultaat";
}
Both the functions are located in 1 controller.
What happens with the current code :
The outcome value is processed for each link element in the datatable sequentially by calling the opleidingController. getOpleidingByCode(o.opl_code). The backing bean method sets the this.opleiding value corresponding to the o.opl_code. Once all the links's outcome values are processed this.opleiding holds the value of the last o.opl_code. Hence, you are seeing last value from the list in the details page.
One Proposed solution:
The this.opleiding value should be set in the controller based on the o.opl_code when you process the details after clicking the link and not when the link is displayed and the outcome is set. You need to
Set outcome="details" in the h:link tag as this value is static and does not change based on any logic in the backing bean and remove method binding.
Pass the value of o.opl_code as a request parameter to the link as given below within the h:link tag.
<f:param name="opl_code" value="#{o.opl_code}"/>
Have the detail backing bean load the this.opleiding value based on the request parameter opl_code. This way you will have details for specific opl_code based on what link you click.

JSF - rich:tabPanel - A backing bean property is called for each tab and not for the active one only

I have 15 tabs containing a similar table, so I have only one backing bean collection of items defining my table. When the tab changes, the collection changes accordingly. So, when the tab is rendered, I am expecting the get method of my collection to be called only once, for my active tab because on screen and in the DOM this tab is the only one with a table. BUT, the get method of my collection is called 15 times, which I guess is because I have 15 tabs.
How do you explain that ? Here is my code.
<rich:tabPanel activeItem="#{myBean.selectedTab}" itemChangeListener="#{myBean.changeItems}" >
<c:forEach items="#{myBean.tabs}" var="t">
<rich:tab id="tab_#{t.code}" header="#{t.libelle}" name="#{t.code}" >
<!-- ############ HEADER ############ -->
<rich:dataTable id="tableHeader_#{t.code}">
<f:facet name="header">
<rich:columnGroup>
<!-- Some columns. Let's say that I have a button like a sort
with a render attribute set to "tab_#{t.code}"
Then all will be correctly rendered but
the get of my collection would have been called 15 times -->
</rich:columnGroup>
</f:facet>
</rich:dataTable>
<!-- ############ DATA ############ -->
<rich:dataTable id="tableData_#{t.code}" value="#{myBean.collectionOfItems}" var="i">
<!-- Some columns -->
</rich:dataTable>
</rich:tab>
</c:forEach>
</rich:tabPanel>
Thank you in advance !
The generation called 15 because the tab captions should be generated (header facets). But if you want to do something #{myBean.selectedTab} specific check this out (or something like that ):
<c:forEach items="#{myBean.tabs}" var="t">
<c:if test="#{t.equals( myBean.selectedTab )}" >
...
</c:if>

row id of jsf datatable

I want to do some opertaions in the row of my JSF datatable, and for that i need and id of row. But when i see html generated through firebug. I notice that id is getting generated only for JSF components not of tr and td. Is there someway by which i can define the id of row(tr)
Here is my code
<h:datatable value = "#{bean.list}" var = "row">
<h:column>
#{row.name}
</h:column>
<h:column>
#{row.address}
</h:column>
<h:column>
#{row.phone no}
</h:column>
<h:column>
<h:selectBooleanCheckbox id="checkbox" value="#{row.sportsStudent}" />
</h:column>
</h:datatable>
There is a button below my datatable which says "Show only sports student" and my list should show only sports student and caption will change to "Show all students" . now all students should be displayed. So i was thinking if i have id of tr . I can just hide/show that row using jquery. So can i do that ?
Thanks in advance.
Tarun Madaan
You have several options. I can propose 2 of them:
You can add class with description to some column in datatable. E.g. for sports student class is sport and ordinary for others. And then you can hide/show all rows, which contains elements with ordinary class.
Filter students on server. Send ajax request which will rerender your table, leaving only sports student. You can do this pretty simple if you use some JSF library with ajax support, e.g. primefaces.

Resources