multiple f:facets for datatable - jsf

I want to use two f:facets: the first row one as a 'header' for the table containing only text, and the second row containing a 'global filter' (label + inputbox).
I have tried countless combinations but failed.
How can I achieve this with JSF/Primefaces?
Here is one example of what I tried:
<p:dataTable var="customer" widgetVar="customerTable" id="dataTable" value="#{customerbean.customerList}" paginator="true" rows="20" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" rowsPerPageTemplate="10,20,50,100" emptyMessage="#{text['table.customer.filter.notfound']}" filteredValue="#{customerbean.filteredCustomers}" editable="true">
<f:facet name="header">
<h:outputText value="#{text['table.customer.header']}" />
</f:facet>
<f:facet name="header2">
<h:outputText value="#{text['table.customer.filter.global']}" />
<p:inputText id="globalFilter" onkeyup="customerTable.filter()" style="width:150px" />
This is my second attempt based on the answer below:
<f:facet name="header">
<p:columnGroup type="header">
<p:row>
<p:column colspan="4">
<h:outputText value="#{text['table.customer.header']}" />
</p:column>
</p:row>
<p:separator/>
<p:row>
<p:column colspan="4">
<h:outputText value="#{text['table.customer.filter.global']}" />
<p:inputText id="globalFilter" onkeyup="customerTable.filter()" style="width:150px" />
</p:column>
</p:row>
</p:columnGroup>
</f:facet>
Whole datatable:
<p:dataTable id="customersTable" var="customer" widgetVar="customerTable" value="#{customerbean.customerList}" paginator="true" rows="20" paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" rowsPerPageTemplate="10,20,50,100" emptyMessage="#{text['table.customer.filter.notfound']}" filteredValue="#{customerbean.filteredCustomers}" editable="true" draggableColumns="true" rowKey="#{customer.id}" selection="#{customerbean.selectedCustomer}" selectionMode="single">
<f:facet name="header">
<p:columnGroup type="header">
<p:row>
<p:column colspan="4">
<h:outputText value="#{text['table.customer.header']}" />
</p:column>
</p:row>
<p:separator/>
<p:row>
<p:column colspan="4">
<h:outputText value="#{text['table.customer.filter.global']}" />
<p:inputText id="globalFilter" onkeyup="customerTable.filter()" style="width:150px" />
</p:column>
</p:row>
</p:columnGroup>
</f:facet>
<p:ajax event="rowEdit" listener="#{customerbean.onEdit}" update="#this"/>
<p:column headerText="Name" sortBy="#{customer.name}" filterBy="#{customer.name}" filterMatchMode="contains">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{customer.name}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{customer.name}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="CPR" sortBy="#{customer.cpr}" filterBy="#{customer.cpr}" filterMatchMode="contains">
<h:outputText value="#{customer.cpr}" />
</p:column>
<p:column headerText="Passport No." sortBy="#{customer.passportno}" filterBy="#{customer.passportno}" filterMatchMode="contains">
<h:outputText value="#{customer.passportno}" />
</p:column>
<p:column headerText="DOB" sortBy="#{customer.dob}" filterBy="#{customer.dob}" filterMatchMode="contains">
<h:outputText value="#{customer.dob}" />
</p:column>
<p:column headerText="Options" style="width:50px">
<p:rowEditor />
</p:column>
<f:facet name="footer">
There are #{fn:length(customerbean.customerList)} customers in total.
</f:facet>
</p:dataTable>

You can't name the facet with whatever name you want. It must be something that the datatable understands. It understands "header", just like it understands "footer", but not "header2" or "footer2".
That said, you can use only one <f:facet name="header"> and inside that you can do whatever you want. You may use a <p:panelGrid columns="1">, or a <p:separator>, or even a simple table, it's just html/css formatting, like you would do anywhere in your page.
There's also a more complex way, if you want to try a little bit harder, using <p:columnGroup type="header"> and many <p:row>s inside it, for example:
<p:columnGroup type="header">
<p:row>
<p:column>
<f:facet name="header">
<h:outputText value="Your header" />
</f:facet>
</p:column>
</p:row>
<p:row>
<p:column>
<f:facet name="header">
<h:outputText value="Filter: "/>
<p:inputText value="#{filter}">
</f:facet>
</p:column>
</p:row>
</p:columnGroup>
See a full example here.

Related

Is there a way to replace the headerText by the first value of my dataTable in Primefaces?

I want my table headers to have the first value of my dataTable.
I know I can change the value of the headerText but for my project I need the header to change according to the values being output.
So from the picture I want 'col1' to be replace by 'jour', 'col2' by 'lundi', 'col3' by 'mardi', etc
<p:dataTable resizableColumns="true" liveResize="true" stripedRows="true" size="large" id="a" var="test"
value="#{testMB1.testlist}" style="padding:20px;" rows="15" paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
currentPageReportTemplate="{startRecord}-{endRecord} of {totalRecords} records"
rowsPerPageTemplate="3,5,10,15,25, 50, 100, 250, 500" rowKey="#{test.id}" scrollable="true" update="mainForm:a"
frozenRows="1">
<f:facet name="header">
<p:outputPanel>
<h:outputText value="Search all fields:" />
<p:inputText filterBy="#{test.id}" id="globalFilter" onkeyup="PF('test').filter()" placeholder="Enter keyword"
filterMatchMode="contains" style="width:200px;height:25px;align:right;" />
</p:outputPanel>
</f:facet>
<p:column headerText="Id" sortBy="#{test.id}">
<h:outputText value="#{test.id}" />
</p:column>
<p:column headerText="col1" sortBy="#{test.col1}" filterMatchMode="contains" filterBy="#{test.col1}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col1}" />
</p:column>
<p:column headerText="col2" sortBy="#{test.col2}" filterMatchMode="contains" filterBy="#{test.col2}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col2}" />
</p:column>
<p:column headerText="col3" sortBy="#{test.col3}" filterMatchMode="contains" filterBy="#{test.col3}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col3}" />
</p:column>
<p:column headerText="col4" sortBy="#{test.col4}" filterMatchMode="contains" filterBy="#{test.col4}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col4}" />
</p:column>
<p:column headerText="col5" sortBy="#{test.col5}" filterMatchMode="contains" filterBy="#{test.col5}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col5}" />
</p:column>
<p:column headerText="col6" sortBy="#{test.col6}" filterMatchMode="contains" filterBy="#{test.col6}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col6}" />
</p:column>
<p:column headerText="col7" sortBy="#{test.col7}" filterMatchMode="contains" filterBy="#{test.col7}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col7}" />
</p:column>
<p:column headerText="col8" sortBy="#{test.col8}" filterMatchMode="contains" filterBy="#{test.col8}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col8}" />
</p:column>
<p:column headerText="col9" sortBy="#{test.col9}" filterMatchMode="contains" filterBy="#{test.col9}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col9}" />
</p:column>
<p:column headerText="col10" sortBy="#{test.col10}" filterMatchMode="contains" filterBy="#{test.col10}"
onkeyup="PF('test').filter()">
<h:outputText value="#{test.col10}" />
</p:column>
</p:dataTable>
My dataTable
Replace all headerText with the code below (according to your mapping object). In the bean, don't forget to verify your list against null, in order not to get a NullPointerException.
<p:column headerText="#{testMB1.testlist.get(0).id}">
Technically speaking a better approach will be to create in the bean a final list, with the columns headers, and call it in the headerText.
If the headers are dynamic, you can use dynamic columns, as suggested by Jasper de Vries

Search and Filter in Primefaces Column Group Headers

When primefaces datatable column headers used for filtering and sorting, it works fine.I want to add column groups to headers, but in that case filtering and sorting seems not possible.
<p:dataTable id="tb1" value="#{hrReportController.staffShiftHistorys}" var="ss"
rows="20" paginator="true" rowsPerPageTemplate="10,20,50"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink}
{PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}">
<f:facet name="header">
<h:outputLabel value="Shift Amendments" style="font-size: 20px"/>
</f:facet>
<p:columnGroup type="header">
<p:row>
<p:column rowspan="2" headerText="Changed at" sortBy="#{ss.createdAt}"/>
<p:column rowspan="2" headerText="Changed by"
sortBy="#{ss.creater.webUserPerson.name}"
filterBy="#{ss.creater.webUserPerson.name}" filterMatchMode="contains"/>
<p:column colspan="4" headerText="Changed from"/>
<p:column colspan="4" headerText="Changed to"/>
</p:row>
<p:row>
<p:column headerText="Code" sortBy="#{ss.staff.code}"
filterBy="#{ss.staff.code}" filterMatchMode="contains"/>
<p:column headerText="Name" sortBy="#{ss.staff.person.nameWithTitle}"
filterBy="#{ss.staff.person.nameWithTitle}" filterMatchMode="contains"/>
<p:column headerText="Roster" sortBy="#{ss.roster.name}"
filterBy="#{ss.roster.name}" filterMatchMode="contains"/>
<p:column headerText="Shift" sortBy="#{ss.shift.name}"
filterBy="#{ss.shift.name}" filterMatchMode="contains"/>
<p:column headerText="Code" sortBy="#{ss.staffShift.staff.code}"
filterBy="#{ss.staffShift.staff.code}" filterMatchMode="contains"/>
<p:column headerText="Name" sortBy="#{ss.staffShift.staff.person.nameWithInitials}"
filterBy="#{ss.staffShift.staff.person.nameWithInitials}"
filterMatchMode="contains"/>
<p:column headerText="Roster" sortBy="#{ss.staffShift.roster.name}"
filterBy="#{ss.staffShift.roster.name}" filterMatchMode="contains"/>
<p:column headerText="Shift"sortBy="#{ss.staffShift.shift.name}"
filterBy="#{ss.staffShift.shift.name}" filterMatchMode="contains"/>
</p:row>
</p:columnGroup>
<p:column headerText="Changed At">
<f:facet name="header"><h:outputLabel value="Changed At"/></f:facet>
<p:outputLabel value="#{ss.createdAt}">
<f:convertDateTime pattern="dd MMM yy- hh:mm a"/>
</p:outputLabel>
</p:column>
<p:column>
<f:facet name="header"><h:outputLabel value="Changed by"/></f:facet>
<p:outputLabel value="#{ss.creater.webUserPerson.name}"/>
</p:column>
<p:column >
<f:facet name="header"><h:outputLabel value="Code"/></f:facet>
<p:outputLabel value="#{ss.staff.code}"/>
</p:column>
<p:column >
<f:facet name="header"><h:outputLabel value="Name"/></f:facet>
<p:outputLabel value="#{ss.staff.person.nameWithTitle}"/>
</p:column>
<p:column >
<f:facet name="header"><h:outputLabel value="Roster"/></f:facet>
<p:outputLabel value="#{ss.roster.name}"/>
</p:column>
<p:column >
<f:facet name="header"><h:outputLabel value="Shift"/></f:facet>
<p:outputLabel value="#{ss.shift.name}"/>
</p:column>
<p:column >
<f:facet name="header"><h:outputLabel value="Code"/></f:facet>
<p:outputLabel value="#{ss.staffShift.staff.code}"/>
</p:column>
<p:column>
<f:facet name="header"><h:outputLabel value="Name"/></f:facet>
<p:outputLabel value="#{ss.staffShift.staff.person.nameWithInitials}"/>
</p:column>
<p:column >
<f:facet name="header"><h:outputLabel value="Roster"/></f:facet>
<p:outputLabel value="#{ss.staffShift.roster.name}"/>
</p:column>
<p:column>
<f:facet name="header"><h:outputLabel value="Shift"/></f:facet>
<p:outputLabel value=" #{ss.staffShift.shift.name}" />
</p:column>
</p:dataTable>

primefaces - edit row without one cell

I have dataTable with row editing, but i dont need to edit one of my cells (user.username). How can i do this in primefaces? Is this possible? I try remove p:cellEditor for one cell but it does not work on my tablet because when I use this in a DataTable, this column is empty.
Thanks!
my code:
<h:form id="form">
<p:growl id="messages" showDetail="true" />
<p:contextMenu for="dataTable">
<p:menuitem value="Delete" update="dataTable" icon="ui-icon-close"
actionListener="#{userMB.deleteUser}" />
</p:contextMenu>
<p:dataTable id="dataTable" var="user" styleClass="DataTableUsers"
value="#{userMB.userList}" paginator="true" rows="5"
rowKey="#{user.user_id}" selection="#{userMB.selectedUser}"
selectionMode="single" filteredValue="#{userMB.filteredUsers}"
editable="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<p:ajax event="rowEdit" immediate="true" listener="#{userMB.onEdit}"
update=":form:messages, :form:dataTable" process="#this" />
<p:column sortBy="name" filterBy="name" id="name" headerText="Name">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{user.name}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{user.name}" required="true"
requiredMessage="Please Enter Name"
validatorMessage="Name is too short!">
<f:validateLength minimum="2"></f:validateLength>
</p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
<p:column sortBy="surname" filterBy="surname" headerText="Surname">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{user.surname}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{user.surname}" required="true"
requiredMessage="Please Enter Surname!"
validatorMessage="Surname is too short!">
<f:validateLength minimum="2"></f:validateLength>
</p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
<p:column sortBy="username" filterBy="username"
headerText="Index number">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{user.username}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{user.username}" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column sortBy="userDescription" filterBy="userDescription"
headerText="descript">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{user.userDescription}" />
</f:facet>
<f:facet name="input">
<p:inputText value="#{user.userDescription}" required="true"
requiredMessage="Please Enter User Description" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column style="width:6%" headerText="Edit">
<p:rowEditor />
</p:column>
<f:facet name="footer">
<p:commandButton value="New User" oncomplete="newUserDialog.show()"
icon="ui-icon-star" title="Creates new user" />
</f:facet>
</p:dataTable>
</h:form>
Just change the component that holds the user.username value to <h:outputText>
<h:outputText value="#{user.username}" />
and you will have the value read-only.

Headers are not shown in exported excel file from primefaces datatable

I have a datatable like this. But it would not export the headers to excel :
<h:form id="formOptionList">
<p:dataTable id="OptionTable"
var="Options"
widgetVar="OptionTable"
value="#{managedBean.options}"
filteredValue="#{managedBean.filteredOptions}"
emptyMessage="No Options found."
rendered="#{managedBean.userPreferences.showTable}"
paginator="true"
rows="10"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="20,50,100"
>
<p:column id="id" headerText="ID" filterBy="id" filterMatchMode="exact" width="12%" rendered="#{managedBean.userPreferences.showID}" >
<h:outputText value="#{options.optionID}" />
</p:column>
....
....
</p:dataTable>
<h:panelGrid columns="1">
<p:panel header="Export All Data">
<h:commandLink>
<p:graphicImage value="../resources/images/menuicons/options.png" />
<p:dataExporter type="xls" target="OptionTable" fileName="Options" />
</h:commandLink>
</p:panel>
</h:panelGrid>
</h:form>
So I changed it to
<p:column id="id" filterBy="id" filterMatchMode="exact" width="12%" rendered="#{managedBean.userPreferences.showID}" >
<f:facet name="header>">
<h:outputText value="Option ID"/>
</f:facet>
<h:outputText value="#{Options.OptionID}" />
</p:column>
And I still don't see the headers in the excel file. Any ideas ?
Headers are not shown in exported excel file from primefaces datatable
Try this:
<p:column id="id" filterBy="#{Options.OptionID}" filterMatchMode="exact" width="12%" rendered="#{managedBean.userPreferences.showID}" >
<f:facet name="header>">
<h:outputText value="Option ID"/>
</f:facet>
<h:outputText value="#{Options.OptionID}" />
</p:column>
You put a <h:outputText value= ""/> after your </f:facet> ?
<p:column>
<f:facet name="header">
<h:outputText value="Your Column Name" />
</f:facet>
<h:outputText value="Your value" />
</p:column>
You can put a new column with display none, from the existing column just put an exporter false
<p:column id="id" filterBy="# Options.OptionID}"filterMatchMode="exact" width="12%" rendered="#anagedBean.userPreferences.showID}"exporter="false">
<f:facet name="header>">
<h:outputText value="Option ID" />
</f:facet>
<h:outputText value="#{Options.OptionID}" />
</p:column>
Add new column with display none and remove all sorting,filtering and rendering
<p:column exporter="true" style="display:none;">
<f:facet name="header>">
<h:outputText value="Option ID"/>
</f:facet>
<h:outputText value="#{Options.OptionID}" />
</p:column>
This works perfectly.

showing different items of a list in dataTable

I would like to show different items of a list in my dataTable
I tried ui:repeat but it's seems not working
I have an object Demande(Classe demande) it has a list of Choix and I want to show for all demandes the choice and the periode(Classe Periode) of each choice(classe Choix)
<p:dataTable id="estivage" var="it" emptyMessage="Aucune demande !"
value="#{demandeController.allDemandes}" paginator="false" style="width: 800px"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,15">
<f:facet name="header">
Liste des Demandes pour la periode d'éstivage
</f:facet>
<p:column style="text-align:center" sortBy="#{it.utilisateur.nom}">
<f:facet name="header">
<h:outputText value="Adherent" />
</f:facet>
<h:outputText value="#{it.utilisateur.nom}" />
<h:outputText value=" " />
<h:outputText value="#{it.utilisateur.prenom}" />
</p:column>
<p:column style="text-align:center" sortBy="#{it.dateDemande}">
<f:facet name="header">
<h:outputText value="Date de la demande" />
</f:facet>
<h:outputText value="#{it.dateDemande}">
<f:convertDateTime pattern="dd/MM/yyyy 'à' HH:mm:ss" />
</h:outputText>
</p:column>
<ui:repeat var="item" value="#{it.listChoix}">
<p:column style="text-align:center">
<f:facet name="header">
<h:outputText value="chalet " />
</f:facet>
<h:outputText value="#{item.chaletChoisi}" />
</p:column>
<p:column style="text-align:center">
<f:facet name="header">
<h:outputText value="periode " />
</f:facet>
<h:outputText value="#{item.periode.libelle}" />
</p:column>
</ui:repeat>
<p:column style="text-align:center">
<f:facet name="header">
<h:outputText value="Mode paiement" />
</f:facet>
<h:outputText value="#{it.modePaiement}">
</h:outputText>
</p:column>
</p:dataTable>
any help please
You have <p:column> in your ui:repeat. It doesn't work well. You could try SubTable from Primefaces.
See example from Primefaces Showcase:
http://www.primefaces.org/showcase/ui/datatableSubTable.jsf
The list of Choix for every Demandesyou can show then in SubTable.
Another possibility is if you use nested DataTables. Use a p:column of "estivage" table and define inside that column another datatable that shows the list of Choix.
<p:dataTable id="estivage" var="it">
<p:column header="choice and periode">
<p:dataTable var="item" value="#{it.listChoix}">
<p:column style="text-align:center">
<f:facet name="header">
<h:outputText value="chalet " />
</f:facet>
<h:outputText value="#{item.chaletChoisi}" />
</p:column>
<p:column style="text-align:center">
<f:facet name="header">
<h:outputText value="periode " />
</f:facet>
<h:outputText value="#{item.periode.libelle}" />
</p:column>
</p:dataTable>
</p:column>
</p:dataTable>

Resources