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
Related
I have this table:
<h:form>
<p:dataTable id="books" value="#{ordersBean.userOrders}" var="book" selection="#{ordersBean.selectedBook}">
<p:column>
<f:facet name="header">Order ID</f:facet>
<h:outputText value="#{book[0]}"/>
</p:column>
<p:column>
<f:facet name="header">Title</f:facet>
<h:outputText value="#{book[1]}"/>
</p:column>
<p:column>
<f:facet name="header"></f:facet>
<p:commandButton id="selectRowBtn" value="select" action="#{ordersBean.showSelectedBook}"/>
</p:column>
</p:dataTable>
</h:form>
I want when i click on each select button, it's row information assigned to selectedBook property and displays it in showSelectedBook() method:
Here is the ordersBean:
private Book selectedBook = new Book();
public Book getSelectedBook() {
return selectedBook;
}
public void setSelectedBook(Book selectedBook) {
this.selectedBook = selectedBook;
}
public void showSelectedBook() {
System.out.println("In selected Book(), book: " + getSelectedBook());
}
But result is this:
In selected Book(), book: null
Should be something like this:
XML code:
<p:commandButton id="selectRowBtn" value="select"
action="#{ordersBean.showSelectedBook}">
<f:param name="bookId" value="#{book[0]}" />
</p:commandButton>
Java bean method:
public void showSelectedBook() {
Map<String,String> params =
FacesContext.getExternalContext().getRequestParameterMap();
int bookId = Integer.valueOf(params.get("bookId"));
for(Book book : bookList){
if(book.bookId == bookId){
selectedBook = book;
break;
}
}
System.out.println("In selected Book(), book: " + getSelectedBook());
}
Beside, you must have knowledge about the patterns for sending parameters to the actions, refer below link.
http://www.mkyong.com/jsf2/4-ways-to-pass-parameter-from-jsf-page-to-backing-bean/
If you want to show the selected book you have to set selectionMode="single" and there's no need to put a commandButton in each row, just specify only one commandButton in the footer facet like this:
<f:facet name="footer">
<p:commandButton id="selectRowBtn" value="select" action="#{ordersBean.showSelectedBook}"/>
</f:facet>
And your main problem here is that you are setting a new Book() to your selectedBook variable, so a null value to your selectedBook , this declaration:
private Book selectedBook = new Book();
Should be :
private Book selectedBook;
You don't have to instantiate a new Book() in your selectedBook.
Take a look at the second Example in this Showcase, to see how it works.
better solution and without select button :
Xml code:
<p:dataTable id="ListBook"
value="#{ordersBean.bookList}"
selection="#{ordersBean.selectedBook}" var="book"
rowKey="#{book.id}" selectionMode="single">
<p:ajax event="rowSelect"
listener="#{ordersBean.onRowSelectDataTable()}"
update="ListBook" />
..... <columns> ..
</p:datatable>
Java bean:
private Book selectedBook=new Book();
private boolean headerButtonsDisabled=true;
//add a List object for all books (bookList) with getter and setter
public boolean isHeaderButtonsDisabled() {
return headerButtonsDisabled;
}
public void setHeaderButtonsDisabled(boolean headerButtonsDisabled) {
this.headerButtonsDisabled = headerButtonsDisabled;
}
public void onRowSelectDataTable() {
this.setHeaderButtonsDisabled(false);
}
public Book getSelectedBook() {
return selectedBook;
}
public void setSelectedBook(Book selectedBook) {
this.selectedBook = selectedBook;
}
i have made jsf 2 webpage using primefaces 3.5 UI , so the webpage are worikng but my dataTable give empaty rows value , it should give me the values that's returned from database query .
note , i have tested the database query and it's working fine , but i think there is problem in sending this data to HTML beans .
my full code :
#ManagedBean
#SessionScoped
public class TableBean implements Serializable {
private static final long serialVersionUID = 1L;
public int model() throws ClassNotFoundException, ReflectiveOperationException, Exception{
try {
// i'm sure the following query return acutal data !
Dbconnection NewConnect = new Dbconnection();
Connection con = NewConnect.MakeConnect();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(" select student_id , teacher_id , apssent_date , interval_id , Day_id from Apsent where class_id = 1" ) ;
int StudentID ;
int ClassID ;
while(rs.next()){
StudentID = rs.getInt(1);
ClassID = rs.getInt(2);
return StudentID ; // or 0 or any value but the web page still give empaty rows value in data grid
}
}
catch (SQLException e){
}
return 0000;
}
my full html code :
<h:form>
<p:dataTable var="car" value="#{tableBean}">
<p:column headerText="Model">
<h:outputText value="#{model.StudentID}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{model.StudentID}" />
</p:column>
<p:column headerText="Manufacturer">
<h:outputText value="#{model.StudentID}" />
</p:column>
<p:column headerText="Color">
<h:outputText value="#{model.StudentID}" />
</p:column>
</p:dataTable>
Well. As I see you totally missunderstand implementation.
Your bean as a model should have private properties i.e.
private List<Object> list;
private int someInteger.
and public accessors to them i.e.:
public setList(List<Object> list){
this.list = list;
}
public getList(){
return list;
}
then you can add some code to get method like this:
public getSomeInteger(){
return myObjectService.findAll(); //myObjectService.findAll() return result of some DB query.
}
then your xhtml datatable should look like:
<p:dataTable var="obj" value="#{yourBean.list}">
<p:column headerText="Model">
<h:outputText value="#{obj.property1}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{obj.property2}" />
</p:column>
<p:column headerText="Manufacturer">
<h:outputText value="#{obj.property3}" />
</p:column>
</p:dataTable>
For better understand JSF read some tutorials:
Mkyong or BalusC
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 ?
I have a table in a database which is used for storing application configuration data.
This is the table structure - it's very simple example:
SessionTTL MaxActiveUsers
---------------------- ----------------------
30 787
I want to display the table data in this way:
<table border="1">
<tr>
<td>SessionTTL</td>
<td>30</td>
</tr>
<tr>
<td>MaxActiveUsers</td>
<td>787</td>
</tr>
<tr>
<td>option</td>
<td>value</td>
</tr>
<tr>
<td>option</td>
<td>value</td>
</tr>
</table>
I tried to display the data using this JSF code and this Java code, but the result was not what I want:
<h:dataTable id="books"
columnClasses="list-column-center,
list-column-right, list-column-center,
list-column-right" headerClass="list-header"
rowClasses="list-row" styleClass="list-
background" value="#{DashboardController.getDashboardList()}" var="store">
<h:column>
<h:outputText value="Session Timeout"/>
<h:outputText value="Maximum Logged Users"/>
</h:column>
<h:column>
<h:outputText value="#{store.sessionTTL} minutes"/>
<h:outputText value="#{store.maxActiveUsers}"/>
</h:column>
</h:dataTable>
public List<Dashboard> getDashboardList()throws SQLException{
List<Dashboard> list = new ArrayList<Dashboard>();
if(ds == null) {
throw new SQLException("Can't get data source");
}
Connection conn = ds.getConnection();
if(conn == null) {
throw new SQLException("Can't get database connection");
}
PreparedStatement ps = conn.prepareStatement("SELECT * from GLOBALSETTINGS");
try{
//get data from database
ResultSet result = ps.executeQuery();
while (result.next()){
Dashboard cust = new Dashboard();
cust.setSessionTTL(result.getString("SessionTTL"));
cust.setMaxActiveUsers(result.getString("MaxActiveUsers"));
list.add(cust);
}
}
catch(Exception e1){
// Log the exception.
}
finally{
try{
ps.close();
conn.close();
}
catch(Exception e2){
// Log the exception.
}
}
return list;
}
How I can display the data the way I want?
Best wishes
You must not assign the get method with the parenthesis. You must use a List attribute from your managed bean.
value="#{DashboardController.getDashboardList()}" //WRONG!
Your managed bean should look like this:
public class DashboardController {
private List<Dashboard> lstDashboard;
public DashboardController() {
try {
lstDashboard = getDashboardList();
} catch (Exception e) {
//log the exception or something else...
}
}
//getter and setter...
public List<Dashboard> getLstDashboard() {
return this.lstDashboard;
}
public void setLstDashboard(List<Dashboard> lstDashboard) {
this.lstDashboard = lstDashboard;
}
//your other methods here...
}
Second, you set the design of every column in your table, not the design of the rows. You're setting 1 column with 2 values and another column with the real output.
Fixing your datatable code:
<h:dataTable id="books"
columnClasses="list-column-center,
list-column-right, list-column-center,
list-column-right" headerClass="list-header"
rowClasses="list-row"
styleClass="list-background"
value="#{DashboardController.lstDashboard}"
var="store">
<h:column>
<f:facet name="header">
<h:outputText value="Session Timeout" />
</f:facet>
<h:outputText value="#{store.sessionTTL} minutes"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="MaxActiveUsers" />
</f:facet>
<h:outputText value="#{store.maxActiveUsers}"/>
</h:column>
</h:dataTable>
#BalusC is the StackOverflow JSF expert. He has a very nice example about using JSF DataTable in his blog entry.
Besides some design flaws that I already remarked in your previous questions, at least you have to use the correct value attribute for your dataTable.
Replace:
value="#{DashboardController.getDashboardList()}"
with:
value="#{DashboardController.dashboardList}"
The "get" prefix will automatically be added. The brackets can be omitted.
getDataList() you can write some normal getter method. you write some of the method dataList() and implement your business code in that method.
Method declaration in the xhtml or jsp file in dataTable in jsf.
<h:dataTable id="books" type="submit" value="#{DashboardController.dataList}" var="dashbord">
<h: column name="ID">
<f:facet name="header">
<h:outputText value="#{dashbord.id}"/>
</f:facet>
</h:column>
...your another columns...
</h:dataTable>
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 =_=