I've got a datatable along with sort, filter and columntoggler.
Firstly, when I select and unselect a column in the same page everything is fine.
As you can see, my first column has disappeared
My problem here is when I go to the next page with pagination tool and if I want to unselect a column, it displays only the column header and not their rows as you can see below :
The initial hidden column is now displayed but we've got a gap. The last column is right now empty and the first one take the value to the second column.
This is my datatable structure :
<p:dataTable id="datatable" var="mon" value="#{X.resultQuery}"
first="#{dataTableController.first}"
resizableColumns="true"
rows="20"
paginator="true"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="30,40,50"
draggableColumns="true"
paginatorPosition="bottom"
selectionMode="single" rowKey="#{mon[4]}"
>
<f:facet name="header">
<p:commandButton id="toggler" type="button" value="Hide Columns" icon="ui-icon-calculator" />
<p:columnToggler datasource="datatable" trigger="toggler">
<p:ajax event="toggle" listener="#{columnTogglerController.onToggle}" />
</p:columnToggler>
</f:facet>
This is my ColumnTogglerController :
public class ColumnTogglerController implements Serializable {
private List<Boolean> list;
/**
* Creates a new instance of ColumnTogglerController
*/
public ColumnTogglerController() {
}
public List<Boolean> getList() {
return list;
}
public void setList(List<Boolean> list) {
this.list = list;
}
#PostConstruct
public void init() {
setList(Arrays.asList(true, true, true, true, true, true, true, true, true, true, true));
}
public void onToggle(ToggleEvent e) {
list.set((Integer) e.getData(), e.getVisibility() == Visibility.VISIBLE);
}
}
Basically my program is based on this blog :
http://blog.primefaces.org/?p=3341
Thanks for you help.
I happen to encounter this recently. The blog actually works. The problem is draggableColumns="true" makes the index of columns change. So, instead of list I used 2 maps:
private final Map<String, Boolean> colVisibilityMap = new HashMap<>();
private final Map<Integer, String> colIndexMap = new HashMap<>();
During initialization, I set the colIndexMap and the colVisibilityMap (and I used the id/clientId as the key).
On column reorder, I update the colIndexMap.
And on toggle, I update the colVisibilityMap base on colIndexMap.
public Map<String, Boolean> getColVisibilityMap() {
return Collections.unmodifiableMap(colVisibilityMap);
}
private String getColumnId(String fullId) {
String[] idParts = fullId.split(":");
return idParts[idParts.length - 1];
}
#PostConstruct
public void init() {
FacesContext context = FacesContext.getCurrentInstance();
DataTable table = (DataTable) context.getViewRoot().findComponent(":form:tableid");
List<UIColumn> columns = table.getColumns();
for (int i = 0; i < columns.size(); i++) {
final String columnId = this.getColumnId(columns.get(i).getClientId());
colIndexMap.put(i, columnId);
colVisibilityMap.put(columnId, true);
});
}
public void onColumnReorder(AjaxBehaviorEvent e) {
List<UIColumn> columns = ((DataTable) e.getSource()).getColumns();
for (int i = 0; i < columns.size(); i++) {
this.colIndexMap.put(i, this.getColumnId(columns.get(i).getClientId()));
}
}
public void onToggle(ToggleEvent e) {
// If we use list here, e.getData() may not be the correct index due to column reordering.
this.colVisibilityMap.put(this.colIndexMap.get((Integer) e.getData()), e.getVisibility() == Visibility.VISIBLE);
}
Here is the code on my JSF page:
<p:dataTable id="tableid" widgetVar="tableWidgetVar" draggableColumns="true" paginator="true"
<!-- ommitted other attributes -->
>
<p:ajax event="colReorder" listener="#{bean.onColumnReorder}"/>
<f:facet name="header">
<p:commandButton id="toggler" type="button" value="Columns"/>
<p:columnToggler datasource="tableid" trigger="toggler">
<p:ajax event="toggle" listener="#{bean.onToggle}"/>
</p:columnToggler>
</f:facet>
<p:column id="col1" visible="#{bean.colVisibilityMap['col1']}">
<!-- ommitted -->
</p:column>
<p:column id="col2" visible="#{bean.colVisibilityMap['col2']}">
<!-- ommitted -->
</p:column>
<!-- and so on... -->
</p:dataTable>
Related
I have a primeface table that shows data from an database stored in a List called notificationList based on a search from. I want the table to be displayed after the submit button is clicked however after I add the rendered attribute the table not displaying at all. Can someone tell what I'm doing wrong and how to fix it? I've tried two methods to do this.
Using rendered=#{not empty notificationSearchBean.results.notificationList} which didn't work even though the list isn't empty (I know bc I printed out the results in the console)
Creating a boolean called visible like in this post "Want to show a data table populated with data after a button click". This also isn't displaying the table regardless of whether visible is set to true or false. What's weird is that I've tried initializing visible with true and the table is still not being rendered.
This is my code for the table:
<h:panelGroup id = "table-wrapper" styleClass="searchResults">
<h:form id="result" >
<p:dataTable id="notTable" var="notifications" value="#{notificationSearchBean.results.notificationList}" row="15">
<p:column headerText="Notification No.">
<h:outputText value="#{notifications.notificationNo}"/>
</p:column>
<p:column headerText="Service">
<h:outputText value="#{notifications.srvce}"/>
</p:column>
<p:column headerText="Operation">
<h:outputText value="#{notifications.oprtn}"/>
</p:column>
<p:column headerText="Service Version">
<h:outputText value="#{notifications.srvceVrsn}"/>
</p:column>
<p:column headerText="Event Date">
<h:outputText value="#{notifications.evntDt}" >
<f:convertDateTime pattern="dd-MMM-yyyy 'at' HH:mm:ss.SSS" />
</h:outputText>
</p:column>
</p:dataTable>
</h:form>
</h:panelGroup>
And code for the submit button:
<h:panelGrid align="center" columns="2">
<p:commandButton value="Start Search" action="#{notificationSearchBean.getAllNotificationsForQuery}" update="table-wrapper"/>
</h:panelGrid>
And the NotificationSearchBean:
#ManagedBean(name = "notificationSearchBean" )
#SessionScoped
public class NotificationSearchBean implements Serializable {
private static final long serialVersionUID = 1L;
private TransactionsDao transactionsDao = (TransactionsDao)((Login)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("login")).getTransDao();
#Inject
private SearchCriteria search;
#Inject
private ResultSet results;
#PostConstruct
public void initialize() {
//setting attributes for search form
}
//getters and setters for search
public ResultSet getResults() {
return results;
}
public void setResults(ResultSet results) {
this.results = results;
}
public String getAllNotificationsForQuery() {
List<NotificationLogT> notifications=transactionsDao.getAllNotifications(this.search);
int temp=notifications.size();
this.results.setNotificationList(notifications);
if(temp==0){
//prints out not results return message
}
return "success";
}
}
And also the ResultSet class:
public class ResultSet implements Serializable {
private List<NotificationLogT> notificationList;
private boolean visible = false;
//private Integer dataSize;
public boolean isVisible() {
return visible;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public List<NotificationLogT> getNotificationList() {
setVisible(true);
return notificationList;
}
public void setNotificationList(List<NotificationLogT> notificationList) {
this.notificationList = notificationList;
}
}
I am using Primefaces 5.0 to create a dynamic datatable.
My DataObject has some required fields and a List of optional "tupel" (key-value pair). The optional list may vary in size. Therefore I need a dynamic mechanism to show a List of DataObject in Primefaces.DataTable.
My approach looks like:
public class DataObject {
private String staticval1;
private String staticval2;
private List<Tupel> optionalValues;
// .. getter, setter, hashCode, toString.....
}
public class Tupel{
private String id;
private String value;
}
#ManagedBean
#ViewScoped
public class TableOverviewBean {
private List<DataObject> data;
#EJB
private IMyDao myDao;
#PostConstruct
public void init() {
data = myDao.findAll();
}
public List<DataObject> getData() {
return data;
}
public void setData(List<DataObject> data) {
this.data = data;
}
}
<h:form>
<p:dataTable value="#{tableOverviewBean.data}" var="data">
<p:column headerText="static1">
<h:outputText value="#{data.staticval1}" />
</p:column>
<p:column headerText="static2">
<h:outputText value="#{data.staticval2}" />
</p:column>
<p:columns value="#{data.optionalValues}" var="opt" headerText="#{opt.id}">
<h:outputText value="#{opt.value}" />
</p:columns>
</p:dataTable>
</h:form>
But this does not work. The dynamic columns are not rendered.
How can I solve my problem?
EDIT:
Expected result:
staticval1 | staticval2 | dynamic_id1 | dynamic_id2 | ... | dynmic_idn
----------------------------------------------------------------------
static1a | static2a | dyna_value1a| dyna_value2a | ... | dyna_valu3a
static1b | static2b | dyna_value1b| dyna_value2b | ... | dyna_valu3b
static1c | static2c | dyna_value1c| dyna_value2c | ... | dyna_valu3c
It isn't possible to define columns based on row data. Imagine that row 1 has 2 columns, row 2 has 6 columns, row 3 has 1 column, etc how would you ever produce a technically valid table in HTML? Each row must have the same amount of columns.
You've 2 options, depending on whether can change the model or not:
If you can't change the model, then you need to replace that <p:columns> by a single <p:column> and loop over the #{data.optionalValues} using a nested loop with e.g. <ui:repeat> or perhaps even another <p:dataTable><p:columns>:
<p:column>
<p:dataTable value=""><!-- Empty string as value forces 1 row. -->
<p:columns value="#{data.optionalValues}" var="opt" headerText="#{opt.id}">
#{opt.value}
</p:columns>
</p:dataTable>
</p:column>
If you can change the model, then you need to let <p:columns value> point to a bean property instead of to a row property, so that it's exactly the same for every row. This works if you replace List<Tupel> optionalValues by Map<String, Tupel> optionalValues where the key is Tupel#id and add a List<String> property to the bean containing all available Tupel#id values.
<p:columns value="#{tableOverviewBean.availableTupelIds}" var="id" headerText="#{id}">
#{data.optionalValues[id].value}
</p:columns>
java:
#Named
#ViewScoped
public class LiveRangeService implements Serializable {
private List< Map<String, ColumnModel> > tableData;
private List<ColumnModel> tableHeaderNames;
public List<Map<String, ColumnModel>> getTableData() {
return tableData;
}
public List<ColumnModel> getTableHeaderNames() {
return tableHeaderNames;
}
public void PlayListMB() {
tableData = new ArrayList< Map<String, ColumnModel> >();
//Generate table header.
tableHeaderNames = new ArrayList<ColumnModel>();
for (int j = 0; j < 5; j++) {
tableHeaderNames.add(new ColumnModel("header "+j, " col:"+ String.valueOf(j+1)));
}
//Generate table data.
for (int i = 0; i < 10; i++) {
Map<String, ColumnModel> playlist = new HashMap<String, ColumnModel>();
for (int j = 0; j < 5; j++) {
playlist.put(tableHeaderNames.get(j).key,new ColumnModel(tableHeaderNames.get(j).key,"row:" + String.valueOf(i+1) +" col:"+ String.valueOf(j+1)));
}
tableData.add(playlist);
}
}
static public class ColumnModel implements Serializable {
private String key;
private String value;
public ColumnModel(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public String getValue() {
return value;
}
}
And XHTML:
<h:form>
<p:dataTable id="tbl" var="result"
value="#{liveRangeService.tableData}"
rendered="#{not empty liveRangeService.tableData}"
rowIndexVar="rowIndex"
>
<f:facet name="header"> header table </f:facet>
<p:column>
<f:facet name="header">
<h:outputText value="序号" />
</f:facet>
<h:outputText value="#{rowIndex+1}" />
</p:column>
<p:columns value="#{liveRangeService.tableHeaderNames}"
var="mycolHeader" columnIndexVar="colIndex">
<f:facet name="header">
<h:outputText value="#{mycolHeader.value}" />
</f:facet>
<h:outputText value="#{result[mycolHeader.key].value}" />
<br />
</p:columns>
</p:dataTable>
</h:form>
That's a example.
In my application I need to decide selection mode dynamically either 'single' or 'multiple' for datatable (I'm using primefaces 5.0) and depends on that selection assigned. Below are the el expressions i have binded.
XHTML:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:head>
<title>Primefaces Data Table</title>
<script type="text/javascript" src="Test.js"/>
</h:head>
<h:body>
<h:form id="form">
<p:growl id="msgs" showDetail="true" />
<p:dataTable id="T" var="car" widgetVar="T_wv" value="#{ECTestScreen.cars}" selectionMode="#{ECTestScreen.selectionMode}" selection="#{ECTestScreen.selectionMode ne 'multiple'? ECTestScreen.selectedCar :ECTestScreen.selectedCars}" rowKey="#{car.id}" paginator="true" rows="5" paginatorAlwaysVisible="true">
<f:facet name="header">
Row Selection on Click
</f:facet>
<p:column headerText="Car Id">
<h:outputText value="#{car.id}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Brand">
<p:inputTextarea id="ta" rows="10" cols="30" style="height: 22px; overflow:auto;" value="#{car.brand}" />
</p:column>
<p:column headerText="Color">
<h:inputText value="#{car.color}" onmouseup="onCellFocus1(event, $(this).parent(), [{name: 'screenletId', value: 'T'}, {name: 'rowIndex', value: '5'}, {name: 'colName', value: 'Color'}]);"/>
</p:column>
<p:ajax event="rowSelect" listener="#{ECTestScreen.onRowSelect}" update=":form:msgs" />
</p:dataTable>
<p:commandButton value="Update Table" actionListener="#{ECTestScreen.onButtonClick}"/>
</h:form>
</h:body>
</html>
Java code:
#ManagedBean(name = "ECTestScreen")
#ViewScoped
public class ECTestScreen implements Serializable {
private static final long serialVersionUID = -855625904411046273L;
private List<String> products = new ArrayList<>();
private List<Integer> rowList = new ArrayList<>();
private List<Car> cars = new ArrayList<>();
private Car selectedCar ;
private List<Car> selectedCars = new ArrayList<>();
private String selectionMode="multiple";
public List<Integer> getRowList() {
return rowList;
}
public void setRowList(List<Integer> rowList) {
this.rowList = rowList;
}
public List<String> getProducts() {
return products;
}
public void setProducts(List<String> products) {
this.products = products;
}
public List<Car> getCars() {
for(int j=1; j<10;j++){
this.cars.add(new Car(j, (2000+j), "Merc-"+j, "Black-"+j));
}
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
public Car getSelectedCar() {
return selectedCar;
}
public void setSelectedCar(Car selectedCar) {
this.selectedCar = selectedCar;
}
public List<Car> getSelectedCars() {
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add("form");
return selectedCars;
}
public void setSelectedCars(List<Car> selectedCars) {
this.selectedCars = selectedCars;
}
public String onButtonClick(){
for(int i=1; i<6; i++){
rowList.add(i);
}
for(int j=1; j<4;j++){
products.add("td="+j);
}
for(int j=1; j<10;j++){
cars.add(new Car(j, (2000+j), "Merc-"+j, "Black-"+j));
}
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add("form");
return "";
}
public String getSelectionMode(){
return selectionMode;
}
public void setSelectionMode(String selectionMode){
selectionMode="multiple";
}
public void onRowSelect(SelectEvent event) {
FacesMessage msg = new FacesMessage("Car Selected: ", ((Car) event.getObject()).getBrand());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onRowUnselect(UnselectEvent event) {
FacesMessage msg = new FacesMessage("Car Unselected: ", ((Car) event.getObject()).getBrand());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
Now the problem is if i assign selectionMode to either single or multiple through el or hardcoding and for selection if i point to only one function(either #{ECTestScreen.selectedCar} or #{ECTestScreen.selectedCars)) it works fine. But using above code if i decide selection mode dynamically either single or multiple depends on that if i add selection through above el the data table selection is not working means when selecting the row the setter is not at all called. and of course pagination also not working. it always stays in first page.
actually in case of single selection expects a single object where as in multiple selection list/array of objects...how to club these two..
Please help..
Primefaces version 5.0
I don't really know why you would make that distinction, since a multiselection dataTable should also cover the single selection requirements.
But if you insist, then i would probably make 2 dataTables - one single and one multiple selection and make them "rendered" based on a boolean.
selectedCars must be an array, not a List. The showcase presents example with a List, but it's not working that way.
I'm using PrimeFace4.0, JSF 2.2, Java, and XHTML. I have a string value that I need to pass from one bean to another. The value is selected on one XHTML page and when the user clicks to select, a new web page is launched. I can see from my server output that the value is successfully collected by the first bean (TestSelectBean), but I can't seem to get it into the next bean (TargetBeanFranz). When a String is hard coded into the bean, it works correctly. However, when I try to use the managed property to call it as per the user input, I get a NullPointer at the line of code (85) where I'm trying to use it.
The first HTML: testselect.xhtml
//irrelevant code
<p:layoutUnit position="center">
<h:form>
<p:selectOneRadio id="Test" value="#{testSelectBean.selectedNameOfExperiments}" >
<f:selectItems id="selectedNameOfExperiments" value="#{testSelectBean.nameofexperiments}" var="entry" itemValue="#{entry.key}" itemLabel="#{entry.value}" />
</p:selectOneRadio>
<p:commandLink id="nonAjax" action="open" actionListener="#{testSelectBean.getParameters}" style="margin-right:20px;" ajax="false">
<h:outputText value="Submit" />
</p:commandLink>
</h:form>
</p:layoutUnit>
The user chosen selectedNameOfExperiments is succsefully passed to TestSelectBean:
#ManagedBean(name = "testSelectBean", eager = true)
#SessionScoped
public class TestSelectBean implements Serializable {
private static final long serialVersionUID = 1L;
protected String selectedNameOfExperiments;
private final Map<String, String> nameofexperiments;
private transient String selected;
public TestSelectBean() throws SQLException {
selected = new String();
nameofexperiments = new HashMap<String, String>();
XYexpdataServiceAdapter xydata = new XYexpdataServiceAdapterImpl();
List<String> dbnameofexperiments = xydata.getNameofexperiments();
for (String ta : dbnameofexperiments) {
nameofexperiments.put(ta, ta);
}
}
public String getSelectedNameOfExperiments() {
return selectedNameOfExperiments;
}
public void setSelectedNameOfExperiments(String selectedNameOfExperiments1) {
this.selectedNameOfExperiments = selectedNameOfExperiments1;
}
public Map<String, String> getNameofexperiments() {
return nameofexperiments;
}
public void getParameters() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("You've selected Experiment:" + selectedNameOfExperiments));
System.out.println("You've selected Experiment:" + selectedNameOfExperiments);
}
}
However, the XHTML FranzwPopup will not launch unless Experiment is hard coded into TargetBeanFranz.
//irrelevant code
<p:layoutUnit position="center">
<p:panelGrid columns="2" style=" font-size: 14">
<h:outputLabel value="Description" style="font-size: 20"/>
<h:outputText value="Neutron-induced production of protons, deuterons and tritons in Copper and Bismuth."/>
<h:outputLabel value="Reference" style="font-size: 20"/>
<h:outputText value="Nuclear Physics A510 (1990) 774-802 (Franz, et. al.)"/>
</p:panelGrid>
<form action="http://localhost:8080/primefaces/faces/handle.xhtml" method="get" name="login" onsubmit="process();
return false;" style="overflow-y: scroll">
Click to display chart data in a table.<br />
<input type="submit" value="Display"/>
</form>
<h:form>
<h:panelGrid columns="4" cellpadding="5">
<p:selectCheckboxMenu id="menu1" value="#{targetBeantFranz.selectedTargets}" label="Targets" filter="true" filterMatchMode="startsWith"
panelStyle="width:220px">
<f:selectItems value="#{targetBeantFranz.targets}" />
</p:selectCheckboxMenu>
<p:selectCheckboxMenu id="menu2" value="#{targetBeantFranz.selectedSecondaries}" label="Secondaries" filter="true" filterMatchMode="startsWith"
panelStyle="width:220px">
<f:selectItems value="#{targetBeantFranz.secondaries}" />
</p:selectCheckboxMenu>
<p:selectCheckboxMenu id="menu3" value="#{targetBeantFranz.selectedReactions}" label="Reactions" filter="true" filterMatchMode="startsWith"
panelStyle="width:220px">
<f:selectItems value="#{targetBeantFranz.reactions}" />
</p:selectCheckboxMenu>
<p:selectCheckboxMenu id="menu4" value="#{targetBeantFranz.selectedBeamEnergies}" label="Beam Energy" filter="true" filterMatchMode="startsWith"
panelStyle="width:220px">
<f:selectItems value="#{targetBeantFranz.beamenergies}" />
</p:selectCheckboxMenu>
</h:panelGrid>
<p:panel header="Resulting Plots">
<p:commandLink id="nonAjax" actionListener="#{targetBeantFranz.getParameters}" style="margin-right:20px;" ajax="false">
<button id="change">Submit Query</button>
</p:commandLink>
<div id="container" style="min-width: 310px; margin: 0 auto"></div>
</p:panel>
</h:form>
</p:layoutUnit>
//more irrelevant
Instead, I get a NPE on line 85 of TargetBeanFranz where I try to initialize Experiment.
//stuff
#ManagedBean(name = "targetBeantFranz", eager = true)
#SessionScoped
public class TargetBeanFranz implements Serializable {
#ManagedProperty(value="#{testSelectBean}")
private TestSelectBean testSelectBean;
public TestSelectBean getTestSelectBean(){
return testSelectBean;
}
public void setTestSelectBean (TestSelectBean testSelectBean) {
this.testSelectBean = testSelectBean;
}
private static final long serialVersionUID = 1L;
private String Experiment;
//more stuff
public TargetBeanFranz() throws SQLException {
targets = new HashMap<String, String>();
selectedTargets = new ArrayList<String>();
secondaries = new HashMap<String, String>();
selectedSecondaries = new ArrayList<String>();
reactions = new HashMap<String, String>();
selectedReactions = new ArrayList<String>();
beamenergies = new HashMap<String, String>();
selectedBeamEnergies = new ArrayList<String>();
seriesDataArray = new ArrayList<String>();
seriesDataArArray = new ArrayList<ArrayList<String>>();
seriesNameArray = new ArrayList<String>();
seriesToolTipArray = new ArrayList<String>();
seriesErrorArray = new ArrayList<String>();
seriesErrorArArray = new ArrayList<ArrayList<String>>();
allselected = new ArrayList<XYexpdata>();
Experiment = testSelectBean.getSelectedNameOfExperiments(); //This is line 85 and where I'm getting the NPE.
XYexpdataServiceAdapter xydata = new XYexpdataServiceAdapterImpl();
List<String> dbtargets = xydata.getTargetNamesbyExperiment(Experiment);
for (String ta : dbtargets) {
targets.put(ta, ta);
}
List<String> dbsecondaries = xydata.getSecondaryNamesbyExperiment(Experiment);
for (String ta : dbsecondaries) {
secondaries.put(ta, ta);
}
List<String> dbreactions = xydata.getReactionNamesbyExperiment(Experiment);
for (String ta : dbreactions) {
reactions.put(ta, ta);
}
List<String> dbbeamenergies = xydata.getBeamEnergybyExperiment(Experiment);
for (String ta : dbbeamenergies) {
beamenergies.put(ta, ta);
}
}
//more code
I think the reason for your problem is, that the signature of the action listener in your command link does not match.
The method in the bean has to be of the following type:
public void getParameters(javax.faces.ActionEvent event) {
.....
}
If you are using Java EE 7 you should also avoid the annotations in the package javax.faces.bean, since they are abandoned. Use CDI beans, it makes life easier:
#Named
#SessionScoped
public class TestSelectBean {
...
}
#Named
#SessionScoped
public class TargetBeanFranz {
#Inject
private TestSelectBean testSelectBean;
....
}
See more about the CDI topic here: Backing beans (#ManagedBean) or CDI Beans (#Named)?
For some strange reason I can't manage to process my data when I'm using <p:ajax event="sort" inside <p:dataTable , while it works just fine for <p:ajax event="page" and <p:ajax event="filter"
I'm using myfaces 2.0.11 with primefaces 3.4 (tried with 4.0 snapshot)
If I edit my cell input and do PAGINATE I do see the updated value of the cell in the listener method
If i edit my cell input and do SORT I do NOT see the updated value of the cell in the listener method, Any Idea why? I mean both p:ajax (sort/page) got the process="#form" so why its does not process? I inspected the network of the chrome dev tools and in both cases (sort/page) the relevant updated values are being sent to the server, but for some reason in the sort listener the values are not updated ,
b.t.w the only suspicious difference between page and sort ajax request is the following parameter that is present only in the sort request is:
my_table_skipChildren:true , what does it mean? skip from processing ?
I can grab the relevant ids+value from the request from the ExternalContext, but it will be last resort only
Here is a really simple example
Session Scoped Bean code:
#ManagedBean
#SessionScoped
public class myBean {
private List<MyObject> myList = new ArrayList<MyObject>();
#PostConstruct
public void init() {
myList.add(new MyObject("1", "2"));
myList.add(new MyObject("11", "22"));
myList.add(new MyObject("111", "222"));
myList.add(new MyObject("1a", "2a"));
myList.add(new MyObject("11a", "22a"));
myList.add(new MyObject("111a", "222a"));
}
public List<MyObject> getMyList() {
return myList;
}
public void setMyList(List<MyObject> myList) {
this.myList = myList;
}
}
MyObject code
public class MyObject {
private String one;
private String two;
public MyObject(String one, String two) {
super();
this.one = one;
this.two = two;
}
public String getOne() {
return one;
}
public void setOne(String one) {
this.one = one;
}
public String getTwo() {
return two;
}
public void setTwo(String two) {
this.two = two;
}
}
XHTML :
<p:dataTable id="my_table" value="#{myBean.myList}"
var="deviceRow" widgetVar="myTable"
paginator="true" rows="4" paginatorPosition="bottom"
paginatorTemplate="{FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}">
<p:ajax process="#form" event="sort" listener="#{myBean.detectSortEvent}"></p:ajax>
<p:ajax process="#form" event="page" listener="#{myBean.detectPageEvent}"></p:ajax>
<p:column id="table_selection_column_one" sortBy="#{deviceRow.one}" filterBy="#{deviceRow.one}">
<f:facet name="header">
<h:outputText value="Column One" />
</f:facet>
<h:inputText id="myRow_One" value="#{deviceRow.one}" />
</p:column>
<p:column id="table_selection_column_two" sortBy="#{deviceRow.two}" filterBy="#{deviceRow.two}">
<f:facet name="header">
<h:outputText value="Column Two" />
</f:facet>
<h:inputText id="myRow_Two" value="#{deviceRow.two}" />
</p:column>
</p:dataTable>
(I also asked it on primefaces forum but got no response)
Tried Andy workaround (adding editable="true" to table, but its no good
The scenario is as follows: change some value of an input text , than click on table column header to do sort
Expectations: Inside detectSortEvent listener I see the updated value inside the list
Reality: Same old value in the list
Regards,
Daniel.