I'm trying to loop over a list and print out some properties using a JSF dataTable as follows:
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:dataTable value="#{clubAdministrationController.members()}" var="member">
<f:facet name="header">
<h:outputText value="Leden" />
</f:facet>
<h:column>
<f:facet name="header">
<h:outputText value="Voornaam" />
</f:facet>
<h:outputText value="#{member.firstName}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Achternaam" />
</f:facet>
<h:outputText value="#{member.lastName}"/>
</h:column>
<h:column>
<h:outputLink id="bewerklid#{member.username}" value="bewerklid/#{member.username}">Wijzig</h:outputLink>
</h:column>
</h:dataTable>
</html>
and I get this result:
<table>
<thead>
<tr>
<th colspan="3" scope="colgroup">Leden</th></tr>
<tr>
<th scope="col">Voornaam</th>
<th scope="col">Achternaam</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td><a id="j_idt12:0:bewerklid" name="j_idt12:0:bewerklid" href="bewerklid/">Wijzig</a></td>
</tr>
<tr>
<td></td>
<td></td>
<td><a id="j_idt12:1:bewerklid" name="j_idt12:1:bewerklid" href="bewerklid/">Wijzig</a></td>
</tr>
</tbody>
</table>
The dataTable iterates the correct amount of times because I have 2 members, but all fields are empty.
When I debug the Java, the members() method returns a list with correctly filled instances and when I print out the values directly the correct values are printed.
#{clubAdministrationController.members().get(0).firstName} <!--displays values correctly -->
When I print out the class name of the member var I get Member$Proxy$_$$_WeldClientProxy
#{member['class'].simpleName} <!-- prints Member$Proxy$_$$_WeldClientProxy -->
I think this suggests that something is going wrong with the dependency injection. I'm using CDI and I know that Weld is a CDI-implementation, and that CDI doesn't inject the actual class, but a proxy-class. I guess a proxy-class is instantiated but the fields must somehow still be copied from the source instance.
I just started learning JSF and CDI, so my question is "what do I have to change to make the dataTable display my Members?"
This is my ClubAdministrationController, when I debug it, the list is filled with my two members:
#Named
#RequestScoped
public class ClubAdministrationController {
#Inject
private MemberDao memberDao;
public List<Member> members() {
List<Member> members = memberDao.getMembers();
return members;
}
}
Since member is a Weld-Proxy you seem to have a class that is #Named member somewhere. (implicit or explicit)
Your data table is now iterating over the correct list (therefore resulting in the correct row count), but always refering to a named class, which does not have the proper values. Most Likely, you have a certain Annotation on your Member.class, which then causes a named WeldProxy (which is empty) to be generated, when you use the el-expression #{member}
(this expression will win against the datatable var member)
Here, you are refering to the instance of member inside the list member():
#{clubAdministrationController.members().get(0).firstName} <!--displays values correctly -->
Here you are refering to the named weld-proxy #{member} - as the class-attribute shows:
#{member['class'].simpleName} <!-- prints Member$Proxy$_$$_WeldClientProxy -->
Changing your var="member" to var="m" and use m.firstName should solve your problem.
To tell you what's wrong with your Member.class, you should include that Code as well.
Related
I am using Bootsfaces datatable to display my data. However, I want to achieve complex header as shown here: https://datatables.net/examples/basic_init/complex_header.html
I tried to add <th rowspan> and <th colspan> directly under header facet in the first dataTableColumn, but that have a ugly empty row at the top.
I also tried to add the whole header facet under <b:dataTable...> tag, before the fist <b:dataTableColumn>, but that header code won't be generated into the html. Any other suggestions? I do not want to switch to primefaces or richfaces as my framework as been fixed.
My code that trying to achieve the complex header looks like below:
<b:dataTable value="#{podStatusListBean.podStatusBeanList}"
var="podStatus"
id="podStatuses">
<b:dataTableColumn footer-style='background-color:orange'
footer-styleclass="{podStatusListBean.footerVisibility}">
<f:facet name="header">
<tr>
<th rowspan="2">Name</th>
<th colspan="2">HR Information</th>
<th colspan="3">Contact</th>
</tr>
</f:facet>
...
This is a new feature we've added to the next BootsFaces version (probably 1.2). As of June 15, 2017, the current version of BootsFaces 1.1.1 only supports complex headers on a per-column basis.
Complex headers per column (supported since BootsFaces 0.8.0):
Add a header facets to the <b:dataTableColumn />, pretty much the way you tried. But keep in mind that BootsFaces already generates the <tr> and <th> tags, so you can nest them a second time. But you can do something like this:
<b:dataTableColumn>
<f:facet name="header">
<ul
style="margin-bottom: 0; list-style-type: none; padding-left: 0">
<li>Price</li>
<li>Engine Power</li>
</ul>
</f:facet>
€ #{car.price}
<br />
#{car.enginePowerKW} KW (#{car.enginePower} hp)
</b:dataTableColumn>
</b:dataTable>
More complex headers (will be supported beginning with BootsFaces 1.2.0):
Add a header facet to the surrounding <b:dataTable /> tag. In this case you're responsible for defining the correct number of table headers. If you skip one, you'll be rewarded by a JavaScript error. In many cases it will even go by unnoticed, but the initialization of the datatable is incomplete, so you'd rather be careful.
<b:dataTable value="#{carPool.carPool}"
var="car"
page-length="5"
page-length-menu="5,10,20">
<f:facet name="header">
<tr>
<th rowspan="2">Car</th>
<th colspan="2">Appearance</th>
<th colspan="2">Technical Data</th>
</tr>
<tr>
<th>Color</th>
<th>Year</th>
<th>Price</th>
<th>Power</th>
</tr>
</f:facet>
<b:dataTableColumn>
#{car.brand} #{car.type}
</b:dataTableColumn>
<b:dataTableColumn value="#{car.color}" />
<b:dataTableColumn value="#{car.year}" order="asc" />
<b:dataTableColumn value="#{car.price}" />
<b:dataTableColumn value="#{car.enginePower}"/>
</b:dataTable>
I am working with JSF 2.2 and Primefaces 6.0. I have a p:dataTable with different p:columns, and each column has many rows. I would like that, whenever column1 input changes, column2 input, in the same row, updates, however, it is not working; it doesn't render.
This is my xhtml code:
<p:dataTable value="#{myBean.objectsList}" var="object">
<p:column headerText="column1">
<table>
<tbody>
<ui:repeat value="#{object.subObjects}" var="object2">
<tr>
<td>
<c:set var="object3" value="#{object2.subObjects}"/>
<h:inputText id="value1#{myBean.toString(object3)}" value="#{object3.value1}">
<f:ajax event="change" listener="#{myBean.doSomething}"
execute="#this" render="#this"/>
</h:inputText>
</td>
</tr>
</ui:repeat>
</tbody>
</table>
</p:column>
<p:column headerText="column2">
<table>
<tbody>
<ui:repeat value="#{object.subObjects}" var="object2">
<tr>
<td>
<c:set var="object3" value="#{object2.subObjects}"/>
<h:inputText value="#{object3.value2}" disabled="disabled">
<f:ajax event="change" listener="#{myBean.doSomething2}"
execute="#this" render="value1#{myBean.toString(object3)}"/>
</h:inputText>
</td>
</tr>
</ui:repeat>
</tbody>
</table>
</p:column>
</p:dataTable>
Each object has many objects as a List.
In f:ajax tag of the first column (column1), you have given #this as value for the attribute render.
Instead, please try giving id of the component column2 or id of the p:dataTableitself.
I have a JSF application with a Data Table. Each row has a 'commandLink'. When the commandLink of a row is clicked then row data must be displayed on console.
I am getting an error when I click on the commandLink, the error is as follows:
component with duplicate id "dataTable1:col1" found
viewId=/UserHome.xhtml
location=E:\workspaces_eclipse\webService\.metadata\.plugins \org.eclipse.wst.server.core\tmp2\wtpwebapps\JSF_Demo\UserHome.xhtml
phaseId=RENDER_RESPONSE(6)
Caused by:
java.lang.IllegalStateException - component with duplicate id "dataTable1:col1" found
at org.apache.myfaces.view.facelets.compiler.CheckDuplicateIdFaceletUtils.checkIds(CheckDuplic ateIdFaceletUtils.java:100)
The error shows that components have same IDs, however I tried to give different 'id' to each element of the data table.
The source code of JSF file 'UserHome.xhtml' is as follows:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org /TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>Resource Net 1.0</title>
<h:outputStylesheet library="css" name="table-style.css"></h:outputStylesheet>
</h:head>
<h:body>
<div align="center">
<table width="90%" height="100%" border="0" style="cellspacing:0; border-radius:10px ;box-shadow: 0px 0px 15px 10px #888888">
<tr>
<td>
<h2><div align="center">Resource Net 1.0</div></h2>
</td>
</tr>
<tr>
<td>
2. Generated by Map :
<h:selectOneMenu value="#{userHomeListener.favCoffee2}">
<f:selectItems value="#{userHomeListener.allDomains}" />
</h:selectOneMenu>
</td>
</tr>
<tr>
<td>
<h:dataTable value="#{userHomeListener.documents}" var="doc"
binding="#{userHomeListener.documentsTable}"
id="dataTable1"
styleClass="order-table"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row"
border="1">
<h:column id="col1">
<f:facet name="header1">Document ID</f:facet>
#{doc.docID}
</h:column>
<h:column id="col2">
<f:facet name="header2">Document Name</f:facet>
#{doc.docName}
</h:column>
<h:column id="col3">
<f:facet name="header3">Document Link</f:facet>
<h:form id="form1">
<h:commandLink id="link" value="#{doc.docLink}" action="#{userHomeListener.getRowData}"></h:commandLink>
</h:form>
</h:column>
<h:column id="col4">
<f:facet name="header4">Upload Date</f:facet>
#{doc.uploadDate}
</h:column>
</h:dataTable>
<h:commandButton value="get row data" ></h:commandButton>
</td>
</tr>
</table>
</div>
</h:body>
Is there some problem with my code? Kindly suggest solutions to this issue.
Thanks in advance.
The binding attribute of the <h:dataTable> is the suspect here. It may lead to this kind of problems when the bean is in a too broad scope and/or when you're doing "wrong things" in the getter/setter of that attribute.
Putting the bean in the request scope and/or looking for alternative ways so that you can get rid of the binding altogether should solve this problem.
The combination of the binding attribute and the name of the command link action method getRowData suggests that you're merely using it to get the current table row. This was indeed the way when using the old JSF 1.x, but not anymore when using the new JSF 2.x. This can be done much better and simpler when you're running a Servlet 3.0 / EL 2.2 capable container (Tomcat 7, Glassfish 3, etc).
<h:dataTable value="#{userHomeListener.documents}" var="doc">
<h:column>
<h:form>
<h:commandLink value="#{doc.docLink}" action="#{userHomeListener.getRowData(doc)}" />
</h:form>
</h:column>
</h:dataTable>
with
public void getRowData(Document doc) {
// ...
}
You see, you can just pass the #{doc} straight as method argument.
See also:
How can I pass selected row to commandLink inside dataTable?
Recommended JSF 2.0 CRUD frameworks
I have a problem with a JSF project.
GlassFish Server 3.1.2
Mojarra 2.1.6
I'm trying to show a table containing the request header fields. Therefor I've written this managed bean:
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
#ManagedBean
#RequestScoped
public class RequestHeader extends LinkedHashMap<String, List<String>> {
private List<String> keys;
#PostConstruct
public void init() {
final HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
keys = Collections.list(request.getHeaderNames());
for (final String key : keys) {
final List<String> value = Collections.list(request.getHeaders(key));
final List<String> oldValue = get(key);
if (oldValue == null) {
put(key, value);
} else {
oldValue.addAll(value);
}
}
}
public List<String> keys() {
return keys;
}
}
This is my JSF page:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>
<title>HTTP request headers</title>
</h:head>
<h:body>
<h:dataTable value="#{requestHeader.keys()}" var="k" border="1">
<f:facet name="header">HTTP request headers</f:facet>
<h:column>
<f:facet name="header">Key</f:facet>
<h:outputText value="#{k}" />
</h:column>
<h:column>
<f:facet name="header">Value</f:facet>
<!-- This forEach seems to be ignored. -->
<c:forEach items="#{requestHeader[k]}" var="v">
<h:outputText value="#{v}" /><br />
</c:forEach>
</h:column>
</h:dataTable>
</h:body>
</html>
Instead of having the values in the second column of the table, the cells are empty:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>HTTP request headers</title>
</head>
<body>
<table border="1">
<thead>
<tr><th colspan="2" scope="colgroup">HTTP request headers</th></tr>
<tr>
<th scope="col">Key</th>
<th scope="col">Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>user-agent</td>
<td></td>
</tr>
<tr>
<td>host</td>
<td></td>
</tr>
<tr>
<td>accept</td>
<td></td>
</tr>
<tr>
<td>accept-language</td>
<td></td>
</tr>
<tr>
<td>accept-encoding</td>
<td></td>
</tr>
<tr>
<td>cache-control</td>
<td></td>
</tr>
<tr>
<td>connection</td>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
I did several tests. <h:outputText value="#{requestHeader[k]}" /> and c:forEach on other lists will work.
Why won't it work this way?
Taghandlers like JSTL tags runs during view build time, while the UI components like JSF <h:xxx> tags runs during view render time. So they doesn't run in sync as you'd expect from the coding. In your code, at the moment the <c:forEach> runs, the <h:dataTable> hasn't run at all and thus its var attribute is not been set and thus #{k} is not available when the <c:forEach> runs and thus it retrieves an empty/non-existent collection.
You need an UI component instead if you want a nested iteration inside another UI component. One of them is Facelets <ui:repeat>.
<ui:repeat value="#{requestHeader[k]}" var="v">
<h:outputText value="#{v}" /><br />
</ui:repeat>
In case you're still on JSF 1.x, use Tomahawk's <t:dataList> instead, or simply another <h:dataTable>.
See also:
JSTL in JSF2 Facelets... makes sense?
JSTL c:if doesn't work inside a JSF h:dataTable
Unrelated to the concrete problem: you don't need a backing bean here at all. All request headers are already as a Map available by the implicit EL object #{header}.
All with all, your approach can be simplified as follows, without any backing bean:
<h:dataTable value="#{header.keySet().toArray()}" var="headerName" border="1">
<f:facet name="header">HTTP request headers</f:facet>
<h:column>
<f:facet name="header">Name</f:facet>
<h:outputText value="#{headerName}" />
</h:column>
<h:column>
<f:facet name="header">Value</f:facet>
<ui:repeat value="#{header[headerName]}" var="headerValue">
<h:outputText value="#{headerValue}" /><br />
</ui:repeat>
</h:column>
</h:dataTable>
See also:
Implicit EL objects
Try to use ui:repeat tag instead of c:forEach.See this link for why ui:repeat use instead of c:forEach.
I have multiple forms that are populated by ThingPageBean. Each of these forms are submitted with a <h:commandButton> where the action is set to call #{thingPageBean.doAmazingThing(oneStuff)}. All fields are static except for contactEmail and contactPhone where I want to use <h:inputText> instead of <h:outputText> so that the user can set a new value if they wish.
The problem is that the new values are not bound to object that is received in doAmazingThing(OneStuff oneStuff) in the ThingPageBean. The old ones remain.
What am I doing wrong? Have I missed some crucial part?
My Bean:
#SuppressWarnings({"unchecked"})
#AutoCreate
#Name("thingPageBean")
#Scope(ScopeType.EVENT)
#Restrict("#{s:hasRole('admin')}")
public class ThingPageBean implements Serializable {
#In
StuffService stuffService;
#In
private StatusMessages statusMessages;
public String doAmazingThing(OneStuff oneStuff) {
return this.stuffService.doAmazingStuffToThing(oneStuff);
}
#Factory(value = "notHandledStuff")
public List<Stuff> notHandledStuff() {
return this.stuffService.searchNotHandledStuff();
}
}
My xhtml file:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jstl/core"
template="/layout/SiteTemplate.xhtml">
<ui:param name="robots" value="noindex"/>
<!-- hide blocks -->
<ui:param name="preContentHide" value="true"/>
<ui:define name="mainContent">
<c:set var="stuff" value="#{notHandledStuff}"/>
<s:div styleClass="section"
rendered="#{stuff == null or stuff.size==0}">
<h:outputText value="#{messages['stuff.no']}"/>
</s:div>
<s:div styleClass="section"
rendered="#{stuff != null and stuff.size>0}">
<br/>
<ui:repeat var="oneStuff" value="#{stuff}">
<h:form id="stuffForm">
<hr style="margin-top:8px;margin-bottom:4px;"/>
<table border="1">
<tr>
<td><b>Company name:</b></td>
<td width="780px"><h:outputText value="#{oneStuff.companyName}"/></td>
</tr>
<tr>
<td><b>street:</b></td>
<td><h:outputText value="#{oneStuff.street}"/></td>
<td/>
</tr>
<tr>
<td><b>zip:</b></td>
<td><h:outputText value="#{oneStuff.zip}"/></td>
<td/>
</tr>
<tr>
<td><b>city:</b></td>
<td><h:outputText value="#{oneStuff.city}"/></td>
<td/>
</tr>
<tr>
<td style="padding-top:10px"><b>contactPerson:</b></td>
<td><h:outputText value="#{oneStuff.contactPersonName}"/></td>
<td/>
</tr>
<tr>
<td><b>contactEmail:</b></td>
<td><h:inputText value="#{oneStuff.contactEmail}"/></td>
<td/>
</tr>
<tr>
<td><b>contactPhone:</b></td>
<td><h:inputText id="contactPhone" value="#{oneStuff.contactPhone}"/></td>
<td/>
</tr>
<h:commandButton id="submit" value="couple"
action="#{thingPageBean.doAmazingThing(oneStuff)}"/>
</td>
</tr>
</table>
</s:div>
</h:form>
</ui:repeat>
<hr style="margin-top:8px;margin-bottom:4px;"/>
</s:div>
<br/>
</div>
</ui:define>
</ui:composition>
Thank you
Jakob
I suggest to change your #Scope(ScopeType.EVENT)
The event (request) context: spans a server request, from restore view to render response.
to a page scope: #Scope(ScopeType.PAGE)
Begins during the invoke application phase prior to rendering a page, and lasts until the end of any invoke application phase of a faces request originating from that page. Non-faces requests do not propagate the page scope.
because you do need these data for a longer conversation not only an event (quotes from Seam Doc)
The problem seemed to be with multiple forms. Moved the <h:form> tag outside <ui:repeat> tag and voila everything works.