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.
Related
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}"..>
I have a rich:dataTable component (RF 4.2.2.Final). I've added the rowclick listener for the table to update a detailed view based on the row selection. Everything was working fine.
But now I'm trying to get my dataTable to have sortable headers. I follow the RF showcase and find out that the row selection doesn't work properly if the data in the dataTable isn't in natural order - it means in order in which the data is in the list in appQueryBean.
But I'm sure that similar case is fine in RF 3.X
My page:
<h:form id="appFormId">
<div>
<rich:dataTable id="appListTableId" value="#{appQuery.applicationList}"
var="row" rendered="#{!empty appQuery.applicationList}"
rows="50" styleClass="styledTable">
<a:ajax
listener="#{appQuery.actionListener(row.id)}"
event="rowclick" render=":applistform:appViewId"/>
<rich:column style="width:10%">
<f:facet name="header">#{msg['ID']}</f:facet>
<h:outputText value="#{row.id}" />
</rich:column>
<rich:column style="width:20%" sortBy="#{row.code}"
sortOrder="#{applicationSortManager.sortOrder}">
<f:facet name="header">
<a:commandLink
value="#{msg['APPLICATION.CODE']}" render="appListTableId"
action="#{applicationSortManager.sortByCode}" /></f:facet>
<h:outputText value="#{row.code}" />
</rich:column>
<rich:column style="width:50%">
<f:facet name="header">#{msg['APPLICATION.NAME']}</f:facet>
<h:outputText value="#{row.name}" />
</rich:column>
<f:facet name="footer">
<rich:dataScroller id="appBottomScroller" for="appListTableId"
renderIfSinglePage="false" immediate="true" align="left"/>
</f:facet>
</rich:dataTable>
<div>
</h:form>
And ApplicationSortManager:
#Named
#SessionScoped
public class ApplicationSortManager implements Serializable{
private SortOrder sortOrder = SortOrder.unsorted;
public void sortByCode(){
if (sortOrder.equals(SortOrder.ascending)) {
setSortOrder(SortOrder.descending);
} else {
setSortOrder(SortOrder.ascending);
}
}
/**
* #return the sortOrder
*/
public SortOrder getSortOrder() {
return sortOrder;
}
/**
* #param _sortOrder the sortOrder to set
*/
public void setSortOrder(SortOrder _sortOrder) {
sortOrder = _sortOrder;
}
}
AppQuery is a ViewScoped component with test actionListener implementation:
public void actionListener(Long _idApplication){
System.out.println("Action listener - appId: " + _idApplication);
}
No matter what is the real order in dataTable - when I click in first row I always get the appId: 1, when second - appId: 2.
How to get the data from row I clicked if the dataTable is sorted?
i wish to display 2 different datatables in each tab of the tabview of primefaces 3.2.
there datatables will fetch data based on the 'type' variable set in the onChange event. but my problem is that the onChange event does not fire at all.
pls check my tabview code to check why this is happening:
<h:form id="frm">
<p:tabView activeIndex="#{equityBean.activeIndex}">
<p:ajax event="tabChange" listener="#{equityBean.onChange}" update=":frm"/>
<p:tab title="NSE" binding="#{equityBean.tbn}">
<p:dataTable binding="#{equityBean.dt}" value="#{equityBean.scripList}" var="scrip">
<f:facet name="header">
Scrip Symbol
</f:facet>
<h:outputText value="#{scrip.scripSymbol}"/>
<f:facet name="header">
Company Name
</f:facet>
<h:outputText value="#{scrip.companyName}"/>
<f:facet name="header">
Volume
</f:facet>
<h:outputText value="#{scrip.totalTradedVolume}"/>
</p:dataTable>
</p:tab>
<p:tab title="BSE" binding="#{equityBean.tb}">
</p:tab>
</p:tabView>
</h:form>
bean:
public void onChange(TabChangeEvent event) {
type=event.getTab().getTitle();
}
edited:
bean code to get datatable value:
public List<MasterScrip> getScripList() {
scripList=new ArrayList<MasterScrip> ();
scripList=getScripByVolumeType(type);
return scripList;
}
private java.util.List<service.MasterScrip> getScripByVolumeType(java.lang.String type) {
service.StatelessWebService port = service.getStatelessWebServicePort();
return port.getScripByVolumeType(type);
}
edited : jpa query
public Collection<MasterScrip> getScripByVolumeType(String type)
{
Collection sm=null;
sm=em.createQuery("select m from MasterScrip m where m.type = :type order by m.totalTradedVolume").setParameter("type", type).setMaxResults(2).getResultList(); // retuens no records
return sm;
}
records are returned but not displayed..
why does this happen? where am i wrong?
Your mistake is here.
listener="#{equityBean.onChange(event)}"
The event object does not exist in EL scope. Remove the argument. You don't need to specify it at all. JSF will supply the necessary action listener argument itself.
listener="#{equityBean.onChange}"
The same is true for all other listener and actionListener attributes. Only in action attribute of UICommand components you can specify custom arguments (which should be passed with real values, not with some random and non-existent variable name).
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>
My goal is to present a jsf page that has Create, Retrieve and Update features.
I decided to create different CDI beans and different composite components for each of this operations and then put it all together in the page.
So far so good, but i just finished and i discovered a really confusing bug, and i don't know how to fix it:
The CDI bean tool that does the CREATE operation is a #RequestScoped bean, so the input fields clean them selves after the request.(See the image bellow)
I have no problem at all with it(Just that warning i cant get rid off), it works fine.
The next gadget i created is a data table that can also edit the data. To do it i needed to use a #SessionScopped CDI bean.(See image below)
Here comes the problem:
When the page is rendered the #SessionScoped bean caches the data in the session, but when new data is inserted, using the #RequestScoped bean,the data goes to the data base but the datatable does not display the new entered values, because are not in the session.
So what should i do?
Here i will show you the two beans:
THE CREATE BEAN
#Named("subjectControllerCreate")
#RequestScoped
public class SubjectControllerCreate implements Serializable {
private Subject currentSubject;
#EJB
private SubjectFacade ejbFacade;
//INITIALIZATION
public SubjectControllerCreate() {
currentSubject = new Subject();
}
//CREATE
public String create() {
try {
currentSubject.setCreationDate(new Date());
getSubjectFacade().create(currentSubject);//Adds the current subject to the database!
JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("SubjectCreated"));
return "";//Can perform a redirect here if we want
//}
//return null;
} catch (Exception e) {
JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
return null;
}
}
THE UPDATE BEAN
#Named("subjectControllerUpdate")
#SessionScoped
public class SubjectControllerUpdate implements Serializable {
//Using DataModel<Subject> instead of List<Subject> is necessary in order to be able to get the current row.
private DataModel<Subject> subjects;
#EJB
private SubjectFacade ejbFacade;
//INITIALIZATION
#PostConstruct
public void init() {
subjects = new ListDataModel<Subject>(getSubjectFacade().findAll());
}
//RETRIEVE
public DataModel<Subject> retrieve() {
return subjects;
}
//UPDATE
public void update() {
getSubjectFacade().edit(subjects.getRowData());
}
//HELP METHODS
//RETURN THE FACADE FOR DATA MANIPULATION(Best practice)
private SubjectFacade getSubjectFacade() {
return ejbFacade;
}
//GETTERS AND SETTERS
public DataModel<Subject> getSubjects() {
return subjects;
}
public void setSubjects(DataModel<Subject> subjects) {
this.subjects = subjects;
}
}
Is it maybe possible to make the data table send some ajax request when detects that the Create dialog closes, to get the rest of the newly entered data?
If yes how could i do it?
This is the markup for my datatable:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core">
<h:form>
<p:dataTable id="allSubjects" var="subject" value="#{subjectControllerUpdate.subjects}" paginator="true" rows="7" >
<p:ajax event="rowEdit" listener="#{subjectControllerUpdate.update()}"/>
<p:column headerText="Name" sortBy="#{subject.name}" style="width:200px" >
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{subject.name}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{subject.name}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column sortBy="#{subject.description}" headerText="Description">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{subject.description}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{subject.description}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column sortBy="#{subject.credits}" headerText="Credits" style="width:50px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{subject.credits}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{subject.credits}" style="width:100%"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Options" style="width:50px">
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
</html>
Ill appreciate your help
Can't you just inject the #SessionScoped bean into the #RequestScoped bean and when create is clicked, call a method refresh in the #SessionScoped bean?