I am having trouble getting the PrimeFaces dataTable component's sort behavior to work as documented. (I am using PrimFaces 4.0, JSF 2.1.12, and Tomcat 7.0.) The problem I am seeing doesn't correspond to any of the other problem reports/discussions related to PF dataTable, as far as I can tell. To explore the problem I created an example based closely on the ShowCase example of using a sorted dataTable, copying the ShowCase source code for the tableBean backing bean (including the generation of local car data for the example; no external DB access is involved) and the supporting Car class. The xhtml is also a very close copy of the ShowCase example:
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form>
<p:dataTable id="dataTable" var="car" value="#{tableBean.carsSmall}">
<f:facet name="header">
Ajax Sorting
</f:facet>
<p:column id="modelHeader" sortBy="#{car.model}">
<f:facet name="header">
<h:outputText value="Model" />
</f:facet>
<h:outputText value="#{car.model}" />
</p:column>
<p:column sortBy="#{car.year}">
<f:facet name="header">
<h:outputText value="Year" />
</f:facet>
<h:outputText value="#{car.year}" />
</p:column>
<p:column sortBy="#{car.manufacturer}">
<f:facet name="header">
<h:outputText value="Manufacturer" />
</f:facet>
<h:outputText value="#{car.manufacturer}" />
</p:column>
<p:column sortBy="#{car.color}">
<f:facet name="header">
<h:outputText value="Color" />
</f:facet>
<h:outputText value="#{car.color}" />
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
When the xhtml is run, the data table shows up, but with only one column displayed as being available for sorting (i.e., with the up/down arrow icon in the header).
The dataTable has two problems:
Only one of the columns (Year) is shown as usable for sorting. (Year is a property of type "int" in the Car class, whereas the other three columns are type String, so one aspect of the problem is that the sortBy="#{car.xxx}" tag is being ignored for String fields.)
The Year column is, in fact, not sortable. Clicking on the up/down arrows of the Year header has no effect. A server callback does occur when the Year header is clicked on, but the table is not sorted. I have tracked down an ELException that occurs during the server callback, in which the code is failing to handle the expression "#{car.0}". That "0" should, no doubt, be "year", and the failed expression no doubt is why no sorting is happening.
Any help would be appreciated in figuring out why this very simple example (copied almost verbatim from the ShowCase sources) of trying to use a PrimeFaces sortable dataTable is giving me grief.
Your firs string is
<p:dataTable id="dataTable" var="car" value="#{tableBean.cars}">
so tableBean has a method
public List<Car> getCars()
{
return carEJB.findAll();
}
but your bean has no variable to save method result after sort.
Solution:
public class CarController
{
...
private List<Car> cars;
...
privare void reset()
{
cars = carEJB.findAll();
}
...
public List<Car> getCars()
{
return cars;
}
}
remove the pound and curly bracket like this:
From this:
<p:column sortBy="#{car.manufacturer}">
To this
<p:column sortBy="manufacturer">
I had the same problem and it was simply because of that.
My datatable was not sorting due to the existence of lazy="true". When I removed that, it worked. I realize you are not using that attribute, however.
Related
I have a primefaces datatable with a lot of similar columns such as
<p:column filterBy="#{element.value}" filterFunction="#{applicationHelperController.filterByNumber}" styleClass="ps-90-header" >
<f:facet name="header">
<p:tooltip for="#next" value="Some header tooltip"/>
<h:outputText id="#{header}_id" value="Some header" styleClass="ps-90-header" />
</f:facet>
<h:outputText value="#{element.value}" />
</p:column>
Is there a way of creating a composite for it such as to write
<mine:column value="#{element.value}" header="Some header" headerTooltip="Some header tooltip" />
I've been searching/trying things for a day now without any real success.
I've managed to use an <ui:include...> with params but it's almost as verbose as the original
<ui:include src="/WEB-INF/includes/countColumn.xhtml" >
<ui:param name="value" value="#{element.value}"/>
<ui:param name="header" value="Some header"/>
<ui:param name="headerTooltip" value="Some header tooltip"/>
</ui:include>
I've tried using taglib as preconized here How to create a composite component for a datatable column? even if it uses richfaces and this solution Column as Composite Component inside DataTable but none work.
I've also read somewhere that <p:column...> should be a direct child of <p:datatable...> so it is not possible but I believe that was with old primefaces version (3 or 4).
So, does anyone know if it is possible with Primefaces 6 or 8 and if so how?
You can use custom Facelet tags to DRY your code.
Simply create tags for columns like:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<p:column ...>
...
</p:column>
</ui:composition>
This is how a table looks in one of our projects:
<dt:dataTable controller="#{controller}"
sortField="activationDate">
<dt:column id="id"/>
<dt:columnDate id="activationDate"/>
...
<dt:dataTable/>
I generated a Primefaces based CRUD website starting from JPA Entities with netbeans and after adjusting the Update dialog to fit my needs I am experiencing several problems. The domain Model is quite easy: I have an entity Invitation which contains several Guests.
#Entity
public class Invitation implements Serializable {
...
#OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "invitationId")
private List<Guest> guestList;
public List<Guest> getGuestList() {
return guestList;
}
...
}
I have an overview page (list.xhtml) where all the invitations are listed and the user can pick one to edit it.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
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:p="http://primefaces.org/ui" template="/template/layout.xhtml">
<ui:define name="content">
<h:form id="InvitationListForm">
<p:dataTable var="invitation" id="datalist"
value="#{invitationController.invitations}" resizableColumns="true"
selectionMode="single" selection="#{invitationController.selected}"
rowKey="#{invitation.invitationId}" paginator="true" rows="10"
rowsPerPageTemplate="10,30,50,100" draggableColumns="true">
<p:ajax event="rowSelect" update="createButton editButton " />
<p:ajax event="rowUnselect" update="createButton editButton " />
<p:column headerText="Name">
<h:outputText id="invitationName" value="#{invitation.name}" />
</p:column>
...
<f:facet name="footer">
<p:commandButton id="createButton" icon="ui-icon-plus"
value="#{msgs.lbl_add_new}" update=":InvitationCreateForm"
oncomplete="PF('InvitationCreateDialog').show()" />
<p:commandButton id="editButton" icon="ui-icon-pencil"
value="#{msgs.lbl_edit}" update=":InvitationEditForm"
oncomplete="PF('InvitationEditDialog').show()"
disabled="#{empty invitationController.selected}" />
</f:facet>
</p:dataTable>
</h:form>
<ui:include src="create.xhtml" />
<ui:include src="edit.xhtml" />
</ui:define>
</ui:composition>
Note that layout.xhtml doesn't contain any form (no nested forms).
The dialog edit.xhtml is divided into 2 parts: one where the user can enter the invitation "head" information and another one with a datatable where she can edit / add / delete guests.
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head></h:head>
<body>
<ui:composition>
<h:form id="InvitationEditForm">
<p:dialog id="InvitationEditDlg" widgetVar="InvitationEditDialog"
modal="true" resizable="false" appendTo="#(body)"
header="#{msgs.lbl_add_new}">
<h:panelGroup id="display">
<p:panelGrid columns="2"
rendered="#{invitationController.selected != null}">
<p:outputLabel value="#{msgs.lbl_name}" for="name" />
<p:inputText id="name"
value="#{invitationController.selected.name}" required="true"/>
...
</p:panelGrid>
<p:dataTable var="aGuest" id="guestTable" style="width: 1200px;"
value="#{invitationController.selected.guestList}"
resizableColumns="false" rowIndexVar="idx" draggableColumns="true">
<p:column width="80" headerText="#{msgs.lbl_name}">
<p:inputText id="guestName" value="#{aGuest.name}" />
</p:column>
...
<p:column width="20">
<p:commandButton
actionListener="#{invitationController.addNewGuest}"
id="addGuestButton" update="guestTable" icon="ui-icon-plusthick"
title="+" />
<p:commandButton
actionListener="#{invitationController.deleteGuest(idx)}"
id="deleteGuestButton" update="guestTable"
icon="ui-icon-minusthick" title="-" immediate="true"
rendered="#{invitationController.selected.guestList.size()>1}" />
</p:column>
</p:dataTable>
<p:commandButton actionListener="#{invitationController.save}"
value="#{msgs.lbl_save}"
update="display,:InvitationListForm:datalist,:growl"
oncomplete="handleSubmit(args,'InvitationEditDialog');" />
<p:commandButton value="#{msgs.lbl_cancel}" immediate="true"
actionListener="#{invitationController.cancel}"
onclick="PF('InvitationEditDialog').hide()" />
</h:panelGroup>
</p:dialog>
</h:form>
</ui:composition>
</body>
</html>
And the Controller
#SessionScoped
#Named
public class InvitationController implements Serializable {
private Invitation selected; //with getter and setter
}
Now, I think my problem should be in the combination of p:dialog and h:form.
The original generated version of edit.xhtml had the form InvitationEditForm nested within the dialog and not the contrary as I posted above. The problem with that was after clicking editButton the dialog was loaded, but the dataTable was always filled with guests of the first Invitation I selected in my session (more strangely, suppose the first invitation in the session had just a guest A: after selecting an Invitation with 2 guests B and C I got A and B displayed). As the controller was returning the right guestList(), I supposed there was a problem with update and inverting form and display solved this problem..
Unfortunately this didn't solve all the problems, as now the actionListener for addGuestButton and deleteGuestButton doesn't get invoked anymore..
I am really confused: can you please help me to fix my code? Thanks in advance!
I have got some problems with my JSF page, and (probably) with backing bean. I have got own template and I fill the content area with some pages. I have got search page with commandbutton and I would like to get data from database (JPA) and than fill the datatable.
Look at my searchpeople.xhtml:
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="template.xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<ui:define name="content">
<h:form id="sampleform">
<p:accordionPanel activeIndex="-1" id="accordingpanle">
<p:tab title="User options" >
<p:growl id="growl" showDetail="true" showSummary="true"/>
<p:commandButton id="searchbutton" action="#{mb_person.search}" value="Szukaj" update="personsearchresulttable" />
</p:tab>
</p:accordionPanel>
<p:dataTable id="personsearchresulttable" var="person" value="#{mb_person.people}" widgetVar="personTable" style="margin-top: 10px" >
<p:column headerText="Id" style="width:10%">
<h:outputText value="#{person.id}" />
</p:column>
<p:column headerText="Name" style="width:20%">
<h:outputText value="#{person.name}" />
</p:column>
<p:column headerText="Surname" style="width:20%">
<h:outputText value="#{person.surname}" />
</p:column>
<p:column headerText="Company">
<h:outputText value="#{person.companyName}" />
</p:column>
<p:column style="width:4%" headerText="Open">
<h:link outcome="persondetails" value="Open">
<!--<f:param name="personid" value="#{person.id}"/>-->
<f:param name="personid" value="10076"/>
</h:link>
</p:column>
</p:dataTable>
</h:form>
</ui:define>
</ui:composition>
And my backingbean with EJB injection.
#ManagedBean(name="mb_person")
public class MB_Person implements Serializable{
#EJB
private PersonFacade personFacade;
private List<PersonAndCompany> people = new ArrayList<PersonAndCompany>();
public MB_Person() {
}
public List<PersonAndCompany> getPeople() {
return people;
}
public void setPeople(List<PersonAndCompany> people) {
this.people = people;
}
public void search() {
int[] range = {0,5};
setPeople(personFacade.findPersonWithMoreThanXProjects(20));
setPeople(personFacade.findPersonAndCompanyName(range));
for(PersonAndCompany p:people){
System.out.println(p.getName());
}
}
public String goToPersonDatailPage(int id){
return "persondetails.jsf?personid="+id;
}
}
I tried small test and printout all data in method search and I received good results.
Someone can help me how to update dataTable using ajax? In this form I have got an exception
Cannot find component with identifier "personsearchresulttable" referenced from "sampleform:accordingpanle:searchbutton".
Relative client IDs are searched relative to parent NamingContainer component. The <p:accordionPanel> is by itself a NamingContainer. So the relative client ID personsearchresulttable would be searched inside the context of the <p:accordionPanel>. However, it's actually outside the panel, inside the <h:form>.
You need to change the relative client ID to be an absolute client ID.
update=":sampleform:personsearchresulttable"
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
When I select a row in my primefaces datatable the row highights, but the selection event is not being invoked and the selected row data is not going to it. Also I notice that my eclipse debugger seems to just hang with PrimeFaces, anyone else notice this? Below is my .xhtml.
<?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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
>
<h:head>
<h:outputStylesheet library="css" name="table-style.css" />
</h:head>
<h:body>
<center>
<p:dataTable var="user" value="#{customer.getCustomerList()}"
selection="#{customer.selectedCustomer}" selectionMode="single"
rowSelectListener="#{custmoer.onUserSelect}" onRowSelectUpdate="userUpdateForm"
onRowUnselectUpdate="userUpdateForm"
paginator="true" rows="5" rowKey="#{user.customerID}" >
<p:column>
<f:facet name="header">
<h:outputText value="Id" />
</f:facet>
<h:outputText value="#{user.customerID}" />
</p:column>
<p:column >
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{user.name}" />
</p:column>
<p:column >
<f:facet name="header">
<h:outputText value="Address" />
</f:facet>
<h:outputText value="#{user.address}" />
</p:column>
</p:dataTable>
<p:inputText id="userUpdateForm" value="#{customer.selectedCustomer.name}" />
</h:form>
</center>
</h:body>
your onXXX attributes are bound to opaque strings, when they're supposed to be bound to javascript fragments (either a method call or a fragment that executes some code). i'm guessing javascript is throwing an exception, and nothing gets sent to the server because execution in the browser halts.
Put the <p:datatable> into a <h:form> component.
May be this is only a missing <h:form> start tag in your post (the </h:form> end tag is included). But forgetting to wrap a data posting component into a <h:form> is a common mistake which leads to the symptoms described by you.
Seems the problem was IE9. Problem disappeared with Firefox.
This can happen if there is another issue in the data table for example in my case the table is editable but I did not add editMode attribute after I added it selection also started working.
I'm using a PrimeFaces DataTable to display records (randomly generated in a sandbox application). I am using the check box selection version. The basic DataTable works perfectly, including the Delete and Cancel buttons (which functionality only really is available from the confirmation dialog). I am trying to add functionality to the DataTable so that when a check box is selected, other controls on the page are enabled or disabled based on the selection.
In other words, if no rows are selected (no check boxes are checked) certain buttons and/or menu items are disabled or not rendered. Selecting one or more rows by clicking the check box should enable or render the controls. I have tried using the built in JavaScript event handlers, but I cannot make this work.
Right now my page displays a DataTable 5 columns: a check box selection column, First Name, Last Name, Age. I made something like this work in another sandbox of mine using simple boolean check boxes and updating a boolean with the onclick event. Unfortunately, there doesn't seem to be anything similar in this DataTable - or if there is I don't know how to implement it.
My index 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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="./newTemplate.xhtml">
<ui:define name="content">
<h:form>
<p:dataTable rowSelectListener="#{tableBean.onRowSelect}" var="data" value="#{tableBean.data}" paginator="true" rows="10"
selection="#{tableBean.selectedNames}">
<f:facet name="header">
Customer List
</f:facet>
<p:column selectionMode="multiple" />
<p:column headerText="Cust ID">
<h:outputText value="#{data.id}" />
</p:column>
<p:column headerText="First Name">
<h:outputText value="#{data.firstName}" />
</p:column>
<p:column headerText="Last Name">
<h:outputText value="#{data.lastName}" />
</p:column>
<p:column headerText="Age">
<h:outputText value="#{data.age}" />
</p:column>
<f:facet name="footer">
<p:commandButton update="deleteList" value="Delete" oncomplete="deleteDlg.show()" />
</f:facet>
</p:dataTable>
<p:dialog header="Delete Selected Records" modal="true" widgetVar="deleteDlg"
>
<h:outputText value="You are about to permanently delete records." /><br /><br />
<h:outputText value="Are you sure you want to continue?" /><br /><br/>
<h:commandButton value="CANCEL" action="#{tableBean.cancelDelete()}" /> <h:commandButton value="Delete" action="#{tableBean.deleteNames()}" />
</p:dialog>
</h:form>
</ui:define>
</ui:composition>
</body>
</html>
Code from my backing bean which may be relevant:
public void deleteNames()
{
for(Data person : selectedNames)
{
data.remove(person);
}
}
public void cancelDelete()
{
for(Data name : selectedNames)
selectedNames = null;
}
public void onRowSelect(SelectEvent event)
{
if(selectedNames == null || selectedNames.length < 1)
setDisable(true);
else
setDisable(false);
}
public boolean isDisable() {
if(selectedNames == null || selectedNames.length < 1)
disable = true;
else
disable = false;
return disable;
}
public void setDisable(boolean disable) {
this.disable = disable;
}
There is a workaround indeed, at least work for me.
extract the datatable.js from primefacess
modify the datatable.js selectRowWithRadio,selectRowWithRadio functions as below
PrimeFaces.widget.DataTable.prototype.selectRowWithCheckbox = function(element) {
...
...
//save state
this.writeSelections();
// added to add instant row selection
this.fireRowSelectEvent(rowId);
// end
}
Append the javascript below to end of your datatable component
<p:datatable widgetVar="wv1" id='mydatatable' ....>
...
<p:datatable/>
<script type="text/javascript">
if(!wv1_main.cfg.onRowSelectUpdate){
wv1.cfg.onRowSelectUpdate="";
}else{
wv1.cfg.onRowSelectUpdate+=" ";
}
wv1.cfg.onRowSelectUpdate+="UPDATE_IDS";
</script>
Replace 'UPDATE_IDS' with your panel ids seperated by space such as "panel1 panel2";
Replace 'wv1' with the value of data table widgetVar property
import the modified js in your jsf page where you want to use instant ajax checkbox/radia selection.
<h:header/>
...
<script type="text/javascript" src="#{CONTEXT_PATH}/resources/js/datatable.js"/>
<h:header/>
you may highligh selected rows with some more modification
Was just searching for solution to the same problem and since JSF 2 / Primefaces are evolving quite fast these days, found more up-to-date solution for Primefaces of version 3.0 or higher.
As per following answer in PrimeFaces forum thread:
http://forum.primefaces.org/viewtopic.php?f=3&t=1373&sid=bbfcd6a343edf586f927cd7ecd7d01b9&start=10#p48388
one can add client-side javascript handler to <p:datatable> component by doing following steps:
1.Add primefaces-extension JAR to your webapp's classpath (this library is also available in central Maven repo under the same name). I tried version 0.6.3 which was the latest at the time of writing, and it worked for me
2.Add pe namespace to corresponding xhtml file:
<?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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:pe="http://primefaces.org/ui/extensions">
...
</html>
3.Add <pe:javascript> as a child element to your <p:datatable> component (can be actually added to any component which implements ClientBehaviorHolder interface) like the following:
<html>
...
<p:dataTable rowSelectListener="#{tableBean.onRowSelect}" var="data" value="#{tableBean.data}" paginator="true" rows="10" selection="#{tableBean.selectedNames}">
<pe:javascript event="rowSelect" execute="onRowSelectedHandler();"/>
...
</p:dataTable>
...
</html>
And that should be it, hope this helps...
You can catch ajax events that are fired when the row is selected.
In your case,
<p:dataTable rowSelectListener="#{tableBean.onRowSelect}"
var="data" value="#{tableBean.data}" paginator="true" rows="10"
selection="#{tableBean.selectedNames}">
<p:ajax event="rowSelectCheckbox" listener="#{tableBean.handleEvent}"
update="buttonThatNeedsToBeRendered"/>
<p:column selectionMode="multiple" />
...
</p:dataTable>
Other useful events that are fired depending on the selection mode of the dataTable are:
rowSelect and rowUnselect
rowSelectCheckbox and rowUnselectCheckbox
rowSelectRadio
toggleSelect