I'm trying to use datatable component but using an array instead of an object inside selection property
Here is the sample from Primefaces showcase
My domain name is EfaDocLabelModel and I updated the CarDataModel(from showcase) to EfaDocLabelModel here is the code .
public EfaDocLabelModel() {
}
public EfaDocLabelModel(List<EfaDocLabelMatch> data) {
super(data);
}
#Override
public EfaDocLabelMatch getRowData(String rowKey) {
List<EfaDocLabelMatch> docLabelList = (List<EfaDocLabelMatch>) getWrappedData();
for (EfaDocLabelMatch docLabel : docLabelList) {
if (docLabel.getDoclabelId().toString().equals(rowKey)) {
return docLabel;
}
}
return null;
}
#Override
public Object getRowKey(EfaDocLabelMatch docLabel) {
return docLabel.getDoclabelId();
}
When user triggered commandbutton inside footer part of datatable ,in my managed bean
I try to get selected rows but it gives
java.lang.NullPointerException
at java.lang.reflect.Array.newArray(Native Method)
at java.lang.reflect.Array.newInstance(Array.java:70)
at org.primefaces.component.datatable.feature.SelectionFeature.decodeMultipleSelection(SelectionFeature.java:53)
at org.primefaces.component.datatable.feature.SelectionFeature.decode(SelectionFeature.java:39)
at org.primefaces.component.datatable.DataTableRenderer.decode(DataTableRenderer.java:53)
I can run the multiple selection from showcase which used CarDataModel but using with the same structure when I modify it to according my need I gat this error.
Here is my bean
public class DocLabelBean implements Serializable {
private List<EfaDocLabelMatch> docLabelMatchList;
private EfaDocLabelMatch[] docLabelArray;
public String updateLabel() {
EfaDocLabelMatch[] selectedDocArray = getDocLabelArray();//I m sure I m
//getting error because selectedDocArray is null.
DTO result = new DTO();
for (EfaDocLabelMatch docLabel : selectedDocArray) {
}
Here is my page necessary code:
<p:dataTable emptyMessage="No Labeled Doc"
var="docLabel" value="#{docLabelBean.docLabelModel}"
selection="#{docLabelBean.docLabelArray}">
<p:column selectionMode="multiple" />
<p:column headerText="Id" >
#{docLabel.doclabelId}
</p:column>
<p:column headerText="Doc No" >
#{docLabel.documentId}
</p:column>
<p:column headerText="Label Key" >
#{docLabel.docLabelKey}
</p:column>
And commanbutton code from page:
<p:commandButton value="Sil" icon="ui-icon-search"
update="#form" process="#form"
action="#{docLabelBean.updateLabel()}" />
I tried ajax=false and other possible error reason mentioned by balusc but still I couldn't resolve the problem
Here is
Bug report .I need to assign selected rows to an list or array if its a real bug is there any alternative ways ?
Related
f:setPropertyActionListener in p:commandLink
How can I bring the data from the setter of the target- Attribut to the getter of the surrounding onclick-attribute?
I want to build an hyperlink within a p:CommandLink (onclick = "window.open('http://www.somewebsite.de ...')" for each row of the datatable. So the Request-parameters of "somewebsite" change depending on the actual row.
I have a working p:commandLink, because I can generate an new browser-window but only with a (constant! [and that is the problem/challenge]) website.
I can also access the needed data from EACH row through the p:commandLink that means the belonging data which I need for the hyperlink-Request-parameters, but I cannot bring it together, because I get a Nullpointer-Exception.
Look the spot which is marked with // HERE SEEMS TO BE THE PROBLEM
<p:dataTable value="#{columnsViewZwei.dataList1}" var="row"
resizableColumns="true"
styleClass="foo"
tableStyleClass="maggtabl2"
tableStyle="maggtabl2"
headerClass="order-table-header"
rowClasses="order-table-odd-row,order-table-even-row">
<p:column headerText="Titel" sortBy="#{row.titel}" filterBy="#{row.titel}">
<h:outputText value="#{row.titel}" />
</p:column>
<p:column headerText="Typ" sortBy="#{row.typ}" filterBy="#{row.typ}">
<h:outputText value="#{row.typ}" />
</p:column>
<p:column headerText="Metadaten" style="width:64px;text-align: center">
<p:commandLink value="show" title="show metatdata" onclick="#{columnsViewZwei.testurl}" >
<f:setPropertyActionListener value="#{row}" target="#{columnsViewZwei.selectedSET}" />
</p:commandLink>
</p:column>
</p:dataTable>
package bbb;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.xml.stream.XMLStreamException;
import bbb.InspireDS;
#ManagedBean
#ViewScoped
public class ColumnsViewZwei implements Serializable {
private String testurl = "";
private InspireDS selectedDataset;
public InspireDS getSelectedDataset() {
System.out.println("getSelectedDataset() ");
return this.selectedDataset;
}
public String selectedDataset() {
selectedDataset = getSelectedDataset();
this.testurl = "window.open('..Info.do?fileIdentifier="+selectedDataset.metadaten+"')";
return testurl;
}
public void setTesturl(String testurl){
this.testurl = "window.open('http://...Info.do?fileIdentifier="+selectedDataset.metadaten+"')";
}
public String getTesturl() {
//selectedDataset = getSelectedDataset();
// HERE SEEMS TO BE THE PROBLEM: NullPointerException probably for selectedDataset
//this.testurl = "window.open('..?fileIdentifier="+selectedDataset.metadaten+"')";
this.testurl = "window.open(' ...')"; // works, but constant hyperlink
return testurl;
}
// This from f:setPropertyActionListener value="#{row}" target="#{columnsViewZwei.selectedSET}
// brings the data I need, but it should be accessable in getTesturl()
public void setSelectedSET(InspireDS inspirDS) {
this.selectedDataset = inspirDS;
this.testurl = "window.open('...do?fileIdentifier="+selectedDataset.metadaten+"')";
}
private List<InspireDS> dataList1;
#ManagedProperty("#{inspireTabelleBean}")
private InspireTabelleBean insTabBean;
#PostConstruct
public void init() {
try {
if(insTabBean==null){System.out.println("s e r v i ce = = n u ll");}
dataList1 = insTabBean.fillListbyparse();
} catch (XMLStreamException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void setService(InspireTabelleBean service) {
this.insTabBean = service;
}
public List<InspireDS> getDataList1() {
return dataList1;
}
public void setInsTabBean(InspireTabelleBean service) {
this.insTabBean = service;
}
}
I'm not able to reproduce your code, i did it a simplified version without datatable.
Instead of window.open function i simply used target="_blank" as explained in this this post.
The error you made is use onclick coupled with f:setPropertyActionListener. The reason why that doesn't function is explained in this post.
faces-redirect=true is needed for change url (read more on this post), and ajax must be false.
However, when you want call bean function through js, take a look to remote command.
xhtml Page:
<h:form id="form_open_window" target="_blank">
<p:commandLink value="show" title="show metatdata" action="#{columnsViewZwei.goToUrl()}" ajax="false" >
<f:setPropertyActionListener value="metadata_parameter" target="#{columnsViewZwei.metadata}" />
</p:commandLink>
</h:form>
Bean Code:
private String testurl = "index";
private String metadata;
public String getMetadata() {
return metadata;
}
public void setMetadata(String metadata) {
this.metadata = metadata;
}
public String goToUrl() {
System.out.println(metadata);
return testurl + "?faces-redirect=true&fileIdentifier=" + metadata;
}
PS: If You don't want deviate too much from your solution, evaluate use of oncomplete instead of onclick, but i didn't try it.
I hope this is useful.
and thank you for your fast answer. I used your suggestions, but what happend was not what i want.
(The table was distorted etc.)
I put in each Method (getter and setter) the System.out.println(...) as you did for goToUrl() {...},
but I did not see any printouts on the console. So it is mysterious which code was invoked.
When I clicked on the commandLink I got a new window with the same facelet "index.xhtml" as i started from. I guess this is the effect of testurl = "index"; My view-file (facelet) has the name "index.xhtml".
I think it is good that you mentioned the other posts so I can try to understand your arguments.
I suppose that I need the value="#{row}" in the f:setPropertyActionListener to access the current row/dataset because in this current row/dataset is the information which i need to build the url to call/access a remote website.
With kind regards,
Yours sincerely
tsitra
ooooooooooooooooo
date:22.12.2014
A possible solution without using a Primefaces component ( control ) was :
<p:dataTable value="#{columnsViewZwei.dataList1}" var="o9"
resizableColumns="true">
<p:column headerText="Titel" sortBy="#{o9.titel}" filterBy="#{o9.titel}">
<h:outputText value="#{o9.titel}" />
</p:column>
<p:column headerText="Typ" sortBy="#{o9.typ}" filterBy="#{o9.typ}">
<h:outputText value="#{o9.typ}" />
</p:column>
<p:column headerText="Metadaten">
show
</p:column>
</p:dataTable>
i have a p:selectOneMenu filled with objects from database.When page is looaded first,
the default item of selectOneMenu must be "please select one" in string type( other items of selectOneMenu are in object type.) When page is loaded first, one data in object type from database is visible as default.I don't want this.how to set default item like "Please select one" in p:selectOneMenu with object from database?
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
template="layout.xhtml">
<ui:define name="pageContent">
<h:form id="silYapilandirmaForm" prependId="true">
<p:panel id="silYapilandirmaPanel" header="#{etiketler.silYapilandirma}" collapsed="true" toggleable="true" >
<p:tabView id="tabView" dynamic="false" activeIndex="0">
<p:tab title="#{etiketler.silIslemleri}" id="silIslemleriTab">
<p:outputPanel id="silIslemleriPanel">
<h:panelGrid id="eshsSecPanelGrid" columns="3" >
<h:outputText value="#{etiketler.eshsSertifika}:*" />
<p:selectOneMenu id="silYapilandirmaSelect" value="#{silYapilandirmaView.seciliEshsSertifika}" effect="fade" effectDuration="100" style="width: 205px" converter="#{entityConverter}">
<f:selectItem itemLabel="Please select one" itemValue="#{null}"/>
<f:selectItems value="#{silYapilandirmaView.eshsSertifikaList}" var="eshsSertifika"
itemLabel="#{eshsSertifika.sertifikaKodAdi}" itemValue="#{eshsSertifika}" />
<p:ajax process="#this" event="change" update="eshsSecPanelGrid,silIslemleriPanel" listener="#{silYapilandirmaView.addListener()}" />
</p:selectOneMenu>
<h:outputText value=""/>
<h:outputText value="#{etiketler.eshsSertifika}:" />
<h:inputText value="#{silYapilandirmaView.seciliEshsSertifika.sertifikaKodAdi}" disabled="true" size="30"/>
<h:outputText value=""/>
<h:outputText value="#{etiketler.silUretimBaslangicSaati}:* " />
<p:inputMask id="silUretimBaslangicSaatiInputMask" value="#{silYapilandirmaView.seciliEshsSertifika.silUretimBaslangicSaati}" mask="99:99:99" size="30" />
<p:message for="silUretimBaslangicSaatiInputMask" display="text" />
<h:outputText value="#{etiketler.silUretimBaslangicPeriyodu}:* " />
<p:inputMask maxlength="4" mask="99?99" id="periyotInputMask" size="30" value="#{silYapilandirmaView.seciliEshsSertifika.silUretimPeriyodu}" >
</p:inputMask>
<p:message for="periyotInputMask" display="text" />
</h:panelGrid>
</p:outputPanel>
</p:tab>
</p:tabView>
</p:panel>
</h:form>
</ui:define>
</ui:composition>
i have addListener method in p:ajax in p:selectOneMenu.This method is working in this way;
you are selecting one object from selectOneMenu and this object is put in the last index of the list filling selectOneMenu ,the object in the last index of the list is put in the index of selected object.I mean you are selecting an object and the index of this object in the list is 2.In total there are five objects in the list ,let we say.selected object whose index is 2 is put in index 4 of the list.The object in index 4 of the list is put in index 2 of the list.I am sorry for my english.The aim of this addListener method,selectOneMenu displays the last item of the list as selected always.Whichever object you select,IT DISPLAYS THE LAST ITEM OF THE LIST.Therefore due to this method , the object i selected is put in the last of the list and it displays as selected to user.The method works fine.
But when page is loaded first , the last item of the list is shown as selected in p:selectOneMenu ,i want "please select" to be shown as default."
My bean class is SilYapilandirmaView.java
#ManagedBean
#ViewScoped
public class SilYapilandirmaView extends BaseView implements Serializable {
#ManagedProperty("#{commonService}")
private CommonService commonService;
private EshsSertifika seciliEshsSertifika;
private List<EshsSertifika> eshsSertifikaList;
#PostConstruct
public void init() {
seciliEshsSertifika=new EshsSertifika();
eshsSertifikaList = (List) commonService.hepsiniGetir(EshsSertifika.class);
seciliEshsSertifika = eshsSertifikaList.get(eshsSertifikaList.size() - 1);
}
public CommonService getCommonService() {
return commonService;
}
public void setCommonService(CommonService commonService) {
this.commonService = commonService;
}
public void addListener() {
if(seciliEshsSertifika ==null)
{
return;
}
int i = 0;
for (EshsSertifika eshsSert : eshsSertifikaList) {
if (seciliEshsSertifika.getId() == eshsSert.getId()) {
eshsSert = eshsSertifikaList.get(eshsSertifikaList.size() - 1);
eshsSertifikaList.set(i, eshsSert);
eshsSertifikaList.set(eshsSertifikaList.size() - 1, seciliEshsSertifika);
break;
}
i++;
}
}
public EshsSertifika getSeciliEshsSertifika() {
return seciliEshsSertifika;
}
public void setSeciliEshsSertifika(EshsSertifika seciliEshsSertifika) {
this.seciliEshsSertifika = seciliEshsSertifika;
}
public List<EshsSertifika> getEshsSertifikaList() {
return eshsSertifikaList;
}
public void setEshsSertifikaList(List<EshsSertifika> EshsSertifikaList) {
this.eshsSertifikaList = EshsSertifikaList;
}
}
When i added following code in init() method ,my code is working perfectly!
seciliEshsSertifika=null;
public void init() {
seciliEshsSertifika=new EshsSertifika();
eshsSertifikaList = (List) commonService.hepsiniGetir(EshsSertifika.class);
seciliEshsSertifika = eshsSertifikaList.get(eshsSertifikaList.size() - 1);
seciliEshsSertifika=null;
}
when page is loaded, "please select one" is visible in p:selectOneMenu,but i don't want to make "seciliEshsSertifika" object equal to null.,is there anybody else coming up with another solution?
Try this. get the object you want to set the first item. (this example i get the first object in the list)
bean.java
EshsSertifika firstItem = eshsSertifikaList.get(0);
xhtml
<f:selectItem itemLabel="#{eshsSertifika.firstItem.sertifikaKodAdi}" itemValue="#{eshsSertifika.firstItem}" />
I've been googling this for 2 days now and trying various attempts that i've seen posted on the web, but nothing seems to be working for me.
I'm trying to get a richfaces 3 datatable to have sorted columns and when i click the column header, nothing actually gets sorted.
Anyone have any idea what i'm missing? Do i need to implement an attribute on my backing bean or something?
<rich:extendedDataTable id="resultsTable" value="#{tableBacking.results}" var="results" rowKeyVar="row">
<rich:column>
<f:facet name="header">
<h:outputText value="Row Number" />
</f:facet>
</rich:column>
<rich:columns value="#{tableBacking.columns == null ? '' : tableBacking.columns}"
var="columns" index="ind" id="column#{ind}"
sortBy="#{results[ind].data}" rendered="#{tableBacking.columns != null}">
<f:facet name="header">
<h:outputText value="#{columns.columnDescription}" />
</f:facet>
<h:outputText value="#{results[ind].data}" />
</rich:columns>
</rich:extendedDataTable>
TableLookupBacking bean
public class TableLookupBacking{
private List<List<TableData>> results = null;
private List<TableData> columns = new ArrayList<TableData>();
public void search() {
getData("");
}
private void getData(String whereClause) {
try {
DataDao dd = new DataDao();
results = dd.getData(WebDataViewerConstants.SCHEMA_NAME, selectedTable, whereClause);
} catch (Exception e) {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Unable to retrieve data with selected search criteria in getData."));
}
}
// columns get set in another method that is triggered off something else the user does
// Getters and Setters
}
I finally figured it out. All i needed to do was to add sortOrder="#{tableBacking.sortOrder[columns]}" to my rich:columns tag and then in my backer just add the following:
private Map<String, Object> sortOrder = new HashMap<String, Object>();
// setter and getter
I am using java 6 jsf 1.2 and richfaces 3.3.3
When I call the function getRowData on the Binded UIDataTable
public void priorityChanged(ValueChangeEvent event) {
Task currentTask = (Task) table.getRowData();
with
<h:selectOneMenu id="id182_#{rkv}" value="#{dataItem.priority}"
valueChangeListener="#{customerAdminHandler.priorityChanged}"
onchange="submit()">
<f:selectItems value="#{customerAdminHandler.priorityTypes}" />
</h:selectOneMenu>
i get an exception on the table.getRowData();
java.lang.IllegalArgumentException
at javax.faces.model.ListDataModel.getRowData(ListDataModel.java:150)
at org.ajax4jsf.model.SequenceDataModel.getRowData(SequenceDataModel.java:147)
at org.ajax4jsf.component.UIDataAdaptorBase.getRowData(UIDataAdaptorBase.java:257)
I bypassed the problem by using
<f:setPropertyActionListener value="#{dataItem}"
target="#{customerProductsHandler.currentApp}" />
instead of a binding table.
the same code worked for me on a clean environment so i guess there is some sort of jar problem.
anyway , for future reference I found the following information usefull for using a binding table
Richfaces 3.3 uses:
org.richfaces.component.html.HtmlDataTable
Richfaces 4 uses:
org.richfaces.component.UIDataTable
jsf1.2 uses:
javax.faces.component.html.HtmlDataTable;
jsf 2 uses:
import javax.faces.model.DataModel;
Have you binded your rich:dataTable to a component attribute of your managed bean? Plus, the type of the attribute must be org.richfaces.component.html.HtmlDataTable, at least this is how we achieved to select one row of the datatable (using the example code of #BalusC here).
The jsp code:
<script type="text/javascript">
function dataTableSelectOneRadio(radio) {
var id = radio.name.substring(radio.name.lastIndexOf(':'));
var el = radio.form.elements;
for (var i = 0; i < el.length; i++) {
if(el[i].name != undefined) {
if (el[i].name.substring(el[i].name.lastIndexOf(':')) == id) {
el[i].checked = false;
}
}
}
radio.checked = true;
}
</script>
<!-- some html/jsp code -->
<rich:dataTable id="dtDocCartera" style="width:100%"
binding="#{busquedaDocCartera.hdtCredito}"
value="#{busquedaDocCartera.lstCredito}" var="credito" rows="15">
<rich:column>
<f:facet name="header">
<h:outputText value="Select" />
</f:facet>
<h:selectOneRadio onclick="dataTableSelectOneRadio(this)"
valueChangeListener="#{busquedaDocCartera.setSelectedItem}">
<f:selectItem itemValue="null"/>
</h:selectOneRadio>
</rich:column>
<rich:column style="text-align:center">
<f:facet name="header">
<h:outputText value="Some Data" />
</f:facet>
<h:outputText value="#{credito.data}" />
</rich:column>
</rich:dataTable>
And this is our managed bean:
#KeepAlive(ajaxOnly=false)
public class PBusquedaDocCartera {
private HtmlDataTable hdtCredito;
private List<ECredito> lstCredito;
//This will be the selected data
private ECredito credito;
//getters and setters for attributes...
public void setSelectedItem(ValueChangeEvent event) {
try {
credito = (ECredito)hdtCredito.getRowData();
} catch (Exception objEx) {
//logging errors...
}
}
}
I am trying to implement table with users' accounts, which can be modified by administrators. I use primefaces (2.2) DataTable component with cellEditor.
I have onRowEditListener which uses manageUsers.onEditRow() method to persist changes in database via UserDAO object.
After loading the page and updating table cell - data in database change properly. Unfortunately, when I am trying to update previous row again - (UserDAO)event.getObject(); returns old object (the one after first change) and data are not updated.
When I reload page (F5) and edit row - then data are changed properly.
How can I update table or how can I get the freshest version of user without reloading page?
Using Primefaces 2.2, JSF 2.1, Glassfish 3.1
PAGE:
<p:column headerText="login" filterBy="#{u.user.login}" filterMatchMode="contains" style="width:150px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{u.user.login}" />
</f:facet>
<f:facet name="input">
<h:form>
<p:inputText value="#{u.user.login}" />
</h:form>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="email" filterBy="#{u.user.email}" filterMatchMode="contains" style="width:150px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{u.user.email}" />
</f:facet>
<f:facet name="input">
<h:form>
<p:inputText value="#{u.user.email}" />
</h:form>
</f:facet>
</p:cellEditor>
</p:column>
//... other fields
<p:column headerText="Options">
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
ManageBean with ApplicationScope (CDI)
#Named
#ApplicationScoped
public class ManageUsers implements Serializable {
#Inject
/** Inject database */
private DB db;
/** List with all leaked data which is loaded from database */
private List<UserDAO> users;
private User selectedUser;
private SelectItem[] manufacturerOptions;
public ManageUsers() {
manufacturerOptions = createFilterOptions();
}
public SelectItem[] getManufacturerOptions() {
return manufacturerOptions;
}
public User getSelectedUser() {
return selectedUser;
}
public void setSelectedUser(User selectedUser) {
this.selectedUser = selectedUser;
}
/** List of users loaded from database */
public void getDataFromDatabase() {
try {
users = db.getUserList();
if (users == null) {
throw new Exception("Pusta lista użytkowników");
}
} catch (Exception ex) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Nie można wyświetlić tabeli wyników",
"Nie udało się pobrać danych, prosimy spróbować ponownie później.");
FacesContext.getCurrentInstance().addMessage(null, message);
}
}
/**
* Get list of leaked Data.
* If list is null then getDataFromDatabase method is used.
* #see DataExplorer.getDataFromDatabase()
*/
public List<UserDAO> getUsers() {
if (users == null) {
getDataFromDatabase();
}
return users;
}
private SelectItem[] createFilterOptions() {
SelectItem[] options = new SelectItem[3];
options[0] = new SelectItem("", "-select-");
options[1] = new SelectItem("true", "Admins");
options[2] = new SelectItem("false", "Users");
return options;
}
public void onEditRow(RowEditEvent event){
UserDAO userDAO = (UserDAO)event.getObject();
try {
userDAO.update();
} catch (UserDAOException ex) {
Log.logger.error("User not edited,"+ex);
}
//getDataFromDatabase();
}
}
You are always returning a new list which is a well known bad practice in JSF, fetching data in getter. Getters may be called several times during JSF lifecycle. Cache your user list in a variable and better to use view scope.
Inline edit/update actually works but you are losing the updated model by returning a new list every time.
I don't know if I really understood your problem but you can easily update your table or even better update your form but implementing a commandButton with update attribute:
Let's say you have a form and it's id is myTableForm, then inside that form you have your dataTable component and a commandButton component. This button will look like this:
<p:commandButton ajax='true' value='PersistData' update='myTableForm' action='if really needed' />
You can refer to an action method only if you need to. Otherwise this button will only update your entire form by implementing an ajax request. Ajax is by default true, but I added that attribute there for explicitly.
Of course you can have another logic design...you don't have to implement a button to do that, you could have some ajax listeners, some javascript functions that will be triggered at page load, edit cells etc... I have chosen a commandButton because it's the easiest way to understand the logic...
Please let me know if this was really what you wanted.
Problem solved.
There are extra h:form around p:inputText =_=