I would like to have a 'Show All' button for a primefaces datatable, however, I'm experiencing some trouble. Here's some test code that demostrates the problem:
Test.xhtml:
...
<h:form>
<p:selectBooleanCheckbox value="#{testBean.showAll}" itemLabel="Show All">
<p:ajax update="#form"/>
</p:selectBooleanCheckbox>
<p:panel id="test">
<p:dataTable id="values" var="value" value="#{testBean.fullList}" filteredValue="#{testBean.filteredList}" paginatorAlwaysVisible="false"
paginator="#{!testBean.showAll}" rows="#{!testBean.showAll ? 2 : null }" widgetVar="valuesTable"
emptyMessage="No records found.">
<p:column id="enum" sortBy="#{value.toString()}" filterBy="#{value.toString()}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Enum" />
</f:facet>
<h:outputText value ="#{value.toString()}"/>
</p:column>
<p:column id="name" sortBy="#{value.name}" filterBy="#{value.name}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{value.name}" />
</p:column>
</p:dataTable>
</p:panel>
</h:form>
...
And here's TestBean.java:
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
#Named(value = "testBean")
#SessionScoped
public class TestBean implements Serializable {
public static enum Value {
ONE, TWO, THREE;
public String getName() {
return name().toLowerCase();
}
#Override
public String toString() {
return this.name();
}
}
/**
* Creates a new instance of TestBean
*/
public TestBean() {
}
private boolean showAll = false;
private List<Value> fullList = Arrays.asList(Value.values());
private List<Value> filteredList;
public boolean isShowAll() {
return showAll;
}
public void setShowAll(boolean showAll) {
this.showAll = showAll;
}
public List<Value> getFullList() {
return fullList;
}
public void setFullList(List<Value> fullList) {
this.fullList = fullList;
}
public List<Value> getFilteredList() {
return filteredList;
}
public void setFilteredList(List<Value> filteredList) {
this.filteredList = filteredList;
}
}
If I don't change tabs, the page works as expected: toggling the 'Show All' button updates the table to show all 3 values, or only two. However, if show all is not checked (only 2 rows are showing), and I click to the 2nd page of the table to view the third record, and then click 'Show All', the table does not update properly. It removes the paginator from the top of the table (as expected), but still only shows the 3rd record. And if I then uncheck show all and navigate back to the first page of the datatable, it is now broken too.
I've tried changing the ajax update statement to the id of the table, but that didn't change the results.
Am I doing something wrong? Thanks in advance.
You have to programmatically set the values you need directly on the DataTable component (I used explicit first and rows bean properties just for more readability):
<h:form>
<p:selectBooleanCheckbox value="#{testBean.showAll}" itemLabel="Show All">
<p:ajax update="#form" />
</p:selectBooleanCheckbox>
<p:panel id="test">
<p:dataTable id="values" var="value" value="#{testBean.fullList}"
filteredValue="#{testBean.filteredList}" paginatorAlwaysVisible="false"
paginator="#{!testBean.showAll}" first="#{testBean.first}" rows="#{testBean.rows}"
widgetVar="valuesTable" emptyMessage="No records found.">
<p:column id="enum" sortBy="#{value.toString()}" filterBy="#{value.toString()}"
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Enum" />
</f:facet>
<h:outputText value="#{value.toString()}" />
</p:column>
<p:column id="name" sortBy="#{value.name}" filterBy="#{value.name}"
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{value.name}" />
</p:column>
</p:dataTable>
</p:panel>
</h:form>
and
#Named
#ViewScoped
public class TestBean implements Serializable
{
private static final long serialVersionUID = 1L;
public static enum Value
{
ONE, TWO, THREE;
public String getName()
{
return name().toLowerCase();
}
#Override
public String toString()
{
return name();
}
}
private boolean showAll = false;
private int first = 0;
private int rows = 2;
private List<Value> fullList = Arrays.asList(Value.values());
private List<Value> filteredList;
public boolean isShowAll()
{
return showAll;
}
public void setShowAll(boolean showAll)
{
this.showAll = showAll;
first = 0;
rows = showAll ? 0 : 2;
filteredList = null;
// get the FacesContext instance
FacesContext context = FacesContext.getCurrentInstance();
// get the current component (p:selectBooleanCheckbox)
UIComponent component = UIComponent.getCurrentComponent(context);
// find DataTable within the same NamingContainer
DataTable table = (DataTable) component.findComponent("values");
// reset first row index
table.setFirst(first);
// reset last row index
table.setRows(rows);
// reset filterd value
table.setFilteredValue(null);
}
// all other getters/setters
}
Tested on Wildfly 10.0.0.Final with JSF 2.3.0-m06 (Mojarra) and PrimeFaces 6.0.2
I had the same problem, was resolved by this steps:
Adding styleClass="all-paginator" to datatable
<p:dataTable id="values" var="value" value="#{testBean.fullList}"
filteredValue="#{testBean.filteredList}" styleClass="all-paginator"..>
Add a getter of number of all records in the controller (TestBean.java) like:
public int getRecordNumber() {
if(CollectionUtils.isEmpty(fullList)){
return 0;
}
return fullList.size();
}
Add the property of the recordNumber at the end of the datatable attribute "rowsPerPageTemplate"
<p:dataTable id="values" var="value" value="#{testBean.fullList}" filteredValue="#{testBean.filteredList}"
styleClass="all-paginator" rowsPerPageTemplate="20,30,40,50,#{testBean.recordNumber}"..>
Related
I'm trying to get selected values from a selectCheckboxMenu, but all I'm getting is null in the console. It doesn't work with selectOneMenu too. Here's my jsf form:
<h:form id="mmaster">
<p:dataTable
value="#{devicesBean.devices}"
var="dev"
widgetVar="dt"
border="1"
paginator="true"
paginatorPosition="top"
rows="10"
>
<f:facet name="header">Devices</f:facet>
<p:column headerText="UDN" sortBy="#{dev.deviceUDN}" filterBy="#{dev.deviceUDN}" filterMatchMode="contains" emptyMessage="No Devices Found">
<h:outputText value="#{dev.deviceUDN}" />
</p:column>
<p:column headerText="FriendlyName" sortBy="#{dev.deviceFriendlyName}" filterBy="#{dev.deviceFriendlyName}" filterMatchMode="contains">
<h:outputText value="#{dev.deviceFriendlyName}" />
</p:column>
<p:column headerText="Model" sortBy="#{dev.deviceModel}" filterBy="#{dev.deviceModel}" filterMatchMode="contains">
<h:outputText value="#{dev.deviceModel}" />
</p:column>
<p:column headerText="Manufacturer" sortBy="#{dev.deviceManufacturer}" filterBy="#{dev.deviceManufacturer}" filterMatchMode="contains">
<h:outputText value="#{dev.deviceManufacturer}" />
</p:column>
<p:column headerText="Type" sortBy="#{dev.deviceType}" filterBy="#{dev.deviceType}" filterMatchMode="contains">
<h:outputText value="#{dev.deviceType}" />
</p:column>
<p:column headerText="Actions">
<p:selectCheckboxMenu value="#{devicesBean.selectAnnotations}">
<f:selectItems value="#{devicesBean.annotations}" />
</p:selectCheckboxMenu>
</p:column>
<p:column>
<p:commandButton value="Annotate" action="#{devicesBean.doSave}" process="#this">
<f:setPropertyActionListener value="#{dev}" target="#{devicesBean.device}" />
</p:commandButton>
</p:column>
</p:dataTable>
</h:form>
I wonder if there is a problem in the bean's scope, And this is my managed bean:
#ManagedBean
public class DevicesBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Device> devices;
private List<String> annotations;
private List<String> selectAnnotations = new ArrayList<String>();
private Device device;
#EJB
IOntoProcessor iop;
#EJB
IDevicesDao idd;
public DevicesBean() {
}
#PostConstruct
public void init() {
setDevices(idd.getAllDevices());
setAnnotations(iop.getAllAnnotations());
}
public List<Device> getDevices() {
return devices;
}
public void setDevices(List<Device> devices) {
this.devices = devices;
}
public List<String> getAnnotations() {
return annotations;
}
public void setAnnotations(List<String> annotations) {
this.annotations = annotations;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
public List<String> getSelectAnnotations() {
return selectAnnotations;
}
public void setSelectAnnotations(List<String> selectAnnotations) {
this.selectAnnotations = selectAnnotations;
}
public void doSave() {
System.out.println(selectAnnotations);
System.out.println(device);
selectAnnotations = new ArrayList<String>();
}
}
You are trying to submit the form through the Button with value Annotate, which has been specified to process itself only:
This will only process the button and its associated form parameters, and no other element within the form.
<p:commandButton value="Annotate" action="#{devicesBean.doSave}" process="#this">
<f:setPropertyActionListener value="#{dev}" target="#{devicesBean.device}" />
</p:commandButton>
Either remove the process="#this", or replace it with process="#form"
<p:commandButton value="Annotate" action="#{devicesBean.doSave}" process="#form">
<f:setPropertyActionListener value="#{dev}" target="#{devicesBean.device}" />
</p:commandButton>
Two, declare your managed bean scope: Either #RequestScope or #SessionScoped will work fine.
In my application I want to execute a client side method before expanding row of <p:dataTable> so I am using onExpandStart="alert('Helo');". But this also is not working for me.
.xhtml code snippet :
<p:dataTable value="#{ExampleDataModel}" lazy="true" paginator="true" onExpandStart="alert('Helo');">
<p:column id="rowToggle" styleClass="rowtoggle">
<p:rowToggler />
</p:column>
<p:rowExpansion>
..........
</p:rowExpansion>
</p:dataTable>
can anyone tell wher I have done wrong? I am using PF 3.4,Mojara(2). Thanks.
Update-1 :
managedBean's code snippet :
#ManagedBean(name = "columnController")
#ViewScoped
public class ColumnController implements Serializable {
private List<ColumnDTO> userNames;
public List<ColumnDTO> getUserNames() {
List<ColumnDTO> columns = new ArrayList<ColumnDTO>();
columns.add(new ColumnDTO(Integer.valueOf(1), "Diganta"));
columns.add(new ColumnDTO(Integer.valueOf(2), "Jayanta"));
columns.add(new ColumnDTO(Integer.valueOf(3), "Proloy"));
return columns;
}
public void setUserNames(List<ColumnDTO> userNames) {
this.userNames = userNames;
}
}
ColumnDTO.java :
public class ColumnDTO implements Serializable {
private static final long serialVersionUID = 4828438441215128064L;
private Integer columnId;
private String columnName;
public ColumnDTO(Integer index, String columnName) {
this.columnId = index;
this.columnName = columnName;
}
//...........getter setter
}
.xhtml code :
<h:head></h:head>
<body>
<h:form>
<p:dataTable value="#{columnController.userNames}" var="name" onExpandStart="alert('Hello')">
<p:column>
<p:rowToggler/>
</p:column>
<p:column>
<h:outputText value="#{name.columnName}" />
</p:column>
<p:rowExpansion>
<h:outputText value="#{name.columnId}" />
</p:rowExpansion>
</p:dataTable>
</h:form>
</body>
</html>
Try <p:ajax event="rowToggle" onstart="alert('Helo');"/> instead of onExpandStart
In the following scenario, where I have several dataTables that I build iterating over a ui:repeat tag, I have experienced that row listener returns null for selected elements that are not in the first table.
In order to understand the model object, I have several menus, and each of them contains several areas.
Any help will be much appreciated.
xhtml below:
<ui:repeat value="#{someBean.menus}" var="menu">
<p:dataTable var="area" value="#{menu.areas}"
rowKey="#{area.id}" selection="#{menu.area}" selectionMode="single">
<p:ajax event="rowSelect" listener="#{someBean.rowSelected}" />
<f:facet name="header">#{menu.name}</f:facet>
<p:column>
<f:facet name="header"></f:facet>
<h:outputText value="#{area.id}" />
</p:column>
<p:column>
<f:facet name="header">Area name</f:facet>
<h:outputText value="#{area.name}" />
</p:column>
</p:dataTable>
</ui:repeat>
ListDataModel java implementation:
public class Areas extends ListDataModel<Area> implements SelectableDataModel<Area>, Serializable {
private static final long serialVersionUID = -9102592194300556930L;
public Areas() {
}
public Areas(List<Area> data) {
super(data);
}
#Override
public Area getRowData(String rowKey) {
#SuppressWarnings("unchecked")
List<Area> areas = (List<Area>)getWrappedData();
for (Area area : areas) {
if (String.valueOf(area.getId()).equals(rowKey)) {
return area;
}
}
return null;
}
#Override
public Object getRowKey(Area area) {
return area.getId();
}
}
public class Menus extends ListDataModel<Menu> implements SelectableDataModel<Menu>, Serializable {
private static final long serialVersionUID = -4079772686830676202L;
public Menus() {
}
public Menus(List<Menu> data) {
super(data);
}
#Override
public Menu getRowData(String rowKey) {
#SuppressWarnings("unchecked")
List<Menu> menus = (List<Menu>)getWrappedData();
for (Menu menu : menus) {
if (String.valueOf(menu.getId()).equals(rowKey)) {
return menu;
}
}
return null;
}
#Override
public Object getRowKey(Menu menu) {
return menu.getId();
}
}
...in the bean someBean
public void rowSelected(SelectEvent event) {
Area selectedArea = (Area)event.getObject(); //This, is null for other tables except the first
System.out.println("SELECTED AREA:" + selectedArea);
//...
}
I am glad to show you the solution: replace ui:repeat with another p:dataTable !!!
<p:dataTable value="#{someBean.menus}" var="menu">
<p:column>
<p:dataTable var="area" value="#{menu.areas}"
rowKey="#{area.id}" selection="#{menu.area}" selectionMode="single">
<p:ajax event="rowSelect" listener="#{someBean.rowSelected}" />
<f:facet name="header">#{menu.name}</f:facet>
<p:column>
<f:facet name="header"></f:facet>
<h:outputText value="#{area.id}" />
</p:column>
<p:column>
<f:facet name="header">Area name</f:facet>
<h:outputText value="#{area.name}" />
</p:column>
</p:dataTable>
</column>
</p:dataTable>
I have a primefaces datatable:
<p:dataTable id="idCrawledDataTable"
var="crawledData"
value="#{crawlerCorpusTreatmentBean.crawledDataModel}"
rowKey="#{crawledData.id}"
rows="10"
scrollable="true"
scrollHeight="300"
selection="#{crawlerCorpusTreatmentBean.crawledData}"
style="width: 850px;">
<f:facet name="header">
RadioButton Based Selection
</f:facet>
<p:column selectionMode="single"
style="width: 12px;"/>
<p:column headerText="id"
style="width: 20px;">
#{crawledData.id}
</p:column>
<p:column headerText="Sritis"
style="40px;">
#{crawledData.domain}
</p:column>
<p:column headerText="URL"
style="width: 450px;">
#{crawledData.url}
</p:column>
</p:dataTable>
It is all filled with values after action method is called. Datatable has radio button selection. When I select one of the radio button and click the command button, I go to some method in which I call my bean, but all values from datatable that my bean has is null.
Showcases shows only how to display data in modal window, I can not find any information on how to pass parameters to managed bean. Maybe someone could help me with this?
Works just for me. Perhaps your data loading logic is wrong (e.g. you're doing it inside a getter method) or the equals() method of the object behind rowKey is broken.
Here's a self-containing kickoff example so that you can at least nail down your own mistake:
<h:form>
<p:dataTable value="#{bean.items}" var="item" selection="#{bean.item}" rowKey="#{item.id}">
<p:column selectionMode="single" />
<p:column headerText="id">#{item.id}</p:column>
<p:column headerText="value">#{item.value}</p:column>
</p:dataTable>
<p:commandButton value="submit" action="#{bean.submit}" />
</h:form>
with
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
private List<Item> items;
private Item item;
#PostConstruct
public void init() {
items = new ArrayList<>();
items.add(new Item(1L, "one"));
items.add(new Item(2L, "two"));
items.add(new Item(3L, "three"));
}
public void submit() {
System.out.println(item);
}
public List<Item> getItems() {
return items;
}
public Item getItem() {
return item;
}
public void setItem(Item item) {
this.item = item;
}
}
where Item has just Long id and String value properties.
I got a problem described in the title. My selectOneMenu doesn't change my Value :/
<h:column>
<f:facet name="header">
<h:outputText value="Vorgesetzter" />
</f:facet>
<h:outputText
value="#{s.manager.surename}, #{s.manager.forename}"
rendered="#{not s.editable}" />
<h:selectOneMenu value="#{s.manager.userID}"
styleClass="inputlabel" id="Vorgesetzter"
rendered="#{s.editable}">
<f:selectItem
itemValue="${null}" itemLabel="-"/>
<f:selectItems value="#{userBean.userList}" var="us"
itemLabel="#{us.surename}, #{us.forename}"
itemValue="#{us.userID}" />
</h:selectOneMenu>
</h:column>
<h:column>
<h:commandButton value="bearbeiten"
action="#{sectionBean.switchEdit(s)}"
rendered="#{not s.editable}" />
<h:commandButton value="speichern"
action="#{sectionBean.updateSection(s)}"
rendered="#{s.editable}" />
<h:commandButton value="abbrechen"
action="#{sectionBean.switchEdit(s)}"
rendered="#{s.editable}" />
</h:column>
this is a piece of the sections.xhtml. It's sourrounded by a form tag.
This is my bean:
package at.ac.htlperg.beans;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import at.ac.htlperg.dao.SectionDAO;
import at.ac.htlperg.model.Section;
#ManagedBean
#SessionScoped
public class SectionBean {
SectionDAO sectionDAO;
public SectionBean() {
sectionDAO = new SectionDAO();
}
public SectionDAO getSectionDAO() {
return sectionDAO;
}
public void setSectionDAO(SectionDAO sectionDAO) {
this.sectionDAO = sectionDAO;
}
public List<Section> getSectionList() {
return sectionDAO.getSectionList();
}
public String deleteSection(Section s) {
sectionDAO.deleteSection(s);
return null;
}
public String switchEdit(Section s) {
sectionDAO.switchEdit(s);
return null;
}
public String saveSection() {
sectionDAO.saveSection(sectionDAO.getSection());
return "/secured/sealed/sections.xhtml";
}
public String updateSection(Section s) {
sectionDAO.updateSection(s);
this.switchEdit(s);
return null;
}
}
the method updateSection should access the Database and does an session.update(s).
But it doesn't save the new values, neither in the selectOneMenu, nor in the usual textbox above (not in the shown code).
Anyone knows what's wrong?
Don't know if it helps, but in JSF 1.2 I had similar issues. The Problem was that h:selectOneMenu returned String values instead of Objects I suspected.
Maybe this "bug" wasn't solved for JSF2.0.
try something like:
// ManagedBean
String userId;
String getUserId(){return this.userId;}
void setUserId(String userId){this.userId = userId;}
// JSF
<h:selectOneMenu value="#{managedBean.userId}"
styleClass="inputlabel" id="Vorgesetzter"
rendered="#{s.editable}">
<f:selectItems value="#{userBean.userList}" var="us"
itemLabel="#{us.surename}, #{us.forename}"
itemValue="#{us.userID}" />
</h:selectOneMenu>
and before working with userId convert it into the Object you want, or just try to use a converter.