editing row in data table
Hi. I'm new to JSF and am having a hard time understanding how modifications to data tables are best managed. I'm able to display all my rows with the modifiable columns rendered as a text inputs, but --for lack of a better description-- I don't understand how to instruct the 'backend' on which row was modified. How do I tell some bean to update row X if I can't supply arguments to action methods? What's the standard implementation (I'm not sure if an action method is the solution for this sort of need)? I don't mind posting to some other resource or adding an event listener- I just can't figure out how the target piece would receive the data.
There are at least three ways of detecting what row was selected by the user. I will suggest the simplest way here.
Bind the dataTable value to a javax.faces.model.ListDataModel (or ArrayDataModel and so on). Example property getter method:
ListDataModel employeeList;
public ListDataModel getEmployeeList() {
if (employeeList != null) return employeeList;
//Get a list of Employee objects from database
ArrayList list = modelLayer.getAllEmployees();
employeeList = new ListDataModel(list);
return employeeList;
}
Then, define the dataTable:
<h:dataTable value="#{bean.employeeList}" ...>
Add a few commandLink components in the table.
<h:commandLink action="#{bean.editEmployee}">
From the action event handler of the command link, simply do:
public String editEmployee() {
//Get the Employee object for the selected row
Employee selectedEmployee = (Employee) employeeList.getRowData();
//...
}
Also, I recommend storing the managed bean in session scope. This is discussed elsewhere in this group.
OK, I'm actually still stuck on this problem. I can implement a 'solution' by specifying an EventChangeListener for each text input, but, rather then executing code for each column change, I want to add a command button for 'update', which then persists all column values in the current row. The problem is, I still can't figure out how to get the current row. Here's my setup:
public class ViewRightBean implements ActionListener,
ValueChangeListener {
private UIData dataModel = new UIData();
public void processAction(ActionEvent event) {
Object rowData = dataModel.getRowData();
new MyOtherBean().doDataUpdate(rowData);
}
}
and my table declaration:
<h:dataTable value="#{ViewRightBean.allViewRights}"
binding="#{ViewRightBean.dataModel}"
var="viewRight">
//all my data columns, then
<h:column>
<f:facet name="header">
<h:outputText value="Action"/>
</f:facet>
<h:commandButton value="save changes">
<f:actionListener type="com.jwt.gui.menus.beans.ViewRightBean"/>
</h:commandButton>
</h:column>
</h:dataTable>
The problem is, getRowData throws an IllegalArgumentException. I'm supposing there must be some error in the binding or field declaration because, within processAction(), the Datatable is non-null, but has a row count of zero and index of -1 (which is probably why I'm getting the IllegalArgumentException). Here's the exact stack Trace. Once again, some pointers would be appreciated.
java.lang.IllegalArgumentExceptionat javax.faces.model.ListDataModel.getRowData(ListDataModel.java:119)at javax.faces.component.UIData.getRowData(UIData.java:286)at com.jwt.gui.menus.beans.ViewRightBean.processAction(ViewRightBean.java:55)at javax.faces.event.ActionEvent.processListener(ActionEvent.java:57)at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:649)at javax.faces.component.UICommand.broadcast(UICommand.java:297)at javax.faces.component.UIData.broadcast(UIData.java:657)at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:267)at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:381)at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:75)at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:200)at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:90)at javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
I figured it out (in case this helps some one else- the previous discussions on datatable in this forum are almost too verbose, focusing on that seesion bug and making it difficult for new JSF developers to find simple answers. ...if they read at my level, at least):
Table Declaration:
//set value to data model instance, not list of value objects
<h:dataTable value="#{ViewRightBean.dataModel}"
var="viewRight">
Bean:
public class ViewRightBean implements ActionListener, ValueChangeListener {
private ListDataModel dataModel;
public ViewRightBean() throws NamingException {
allViewRights = new MenuClient().getMenuFacade().findAllViewRight();
dataModel = new ListDataModel(allViewRights);
}
I have the same issue but I am having a hard time figuring out your final solution. It would be greatly appreciated if you could clearly document your solution.