I use primefaces 3.1 and I have a datatable that shows paginated data, whose columns are constructed based on the data of the page and rendered via <p:columns/> tag. With this approach, different pages of the same datatable can have different columns. I tought it would re-render columns on pagination by default, but it doesn't. Ive tried <p:ajax event="page" update="myTable"/> and <p:ajax event="page" update="myTableContainer"/> with any luck.
Is there a way to re-render the whole datatable when pagination is triggered, so not only content but column headers are showed properly?
Edit: Heres some code sample as you requested.
Ive made my own implementation of LazyDataModel and extended it overriding the load method implementation:
#Override
public List<StockItem> load(int i, int i1, String string, SortOrder sortOrder, Map<String, String> map) {
List<StockItem> stockItems = super.load(i, i1, string, sortOrder, map);
inventoryMovements = service.listInventoryMovements(stockItems, fromDate, toDate);
stockOperations = new HashSet<StockOperation>();
quantityTypes = new HashSet<QuantityType>();
for (Map.Entry<StockItem, ItemMovements> entry : inventoryMovements.entrySet()) {
quantityTypes.addAll(entry.getValue().getStartingQuantities().keySet());
quantityTypes.addAll(entry.getValue().getEndingQuantities().keySet());
stockOperations.addAll(entry.getValue().getOperationsApplied().keySet());
}
return stockItems;
}
As you see in the method, i fill both stockOperations and quantityTypes on every page load. These two correspond to my actual page columns. (These are atributes in my LazyDataModel implementation with their corresponding getters)
<p:dataTable id="movementsTable" var="item"
value="#{inventoryMovementsBean.view}"
rowIndexVar="rowIndex"
paginator="true"
rows="25">
<p:column headerText="Item">
<h:outputText value="#{item.label}" />
</p:column>
<p:columns value="#{inventoryMovementsBean.view.quantityTypes}" var="quantityType" columnIndexVar="quantityTypeIndex">
<f:facet name="header">
#{quantityType.description}
</f:facet>
<h:outputText value="#{inventoryMovementsBean.view.getStartingQuantity(item, quantityType)} => #{inventoryMovementsBean.view.getEndingQuantity(item, quantityType)}" />
</p:columns>
<p:columns value="#{inventoryMovementsBean.view.stockOperations}" var="stockOperation" columnIndexVar="stockOperationIndex">
<f:facet name="header">
#{stockOperation.name}
</f:facet>
<h:outputText value="#{inventoryMovementsBean.view.getOperationValue(item, stockOperation)}" />
</p:columns>
</p:dataTable>
inventoryMovementsBean.view is my LazyDataModel instance and methods getOperationValue(item, stockOperation), getStartingQuantity(item, quantityType) and getEndingQuantity(item, quantityType) are the ones that give me the content given an item and a column.
Ive already made a debug, and im pretty sure the whole data is loaded propertly, it is just a display problem. Here are some screenshots as additional information.
These images correspond to:
Initial render (Page 1).
Actual render after pagination (Page 3)
Expected render after pagination (Page 3)
If you use Primefaces, There is an option like lazyLoading.If you specify true,then all the client side stuff will be handled in server side.For more
http://www.primefaces.org/showcase/ui/datatableLazy.jsf
Related
I am building a single page application with Primefaces 6.1, JSF 2.2 and running it on Wildfly, which has an option to search for users. Initial view renders only search panel with various filters and on click of search, user table will be queried and set of data is returned and then a block is rendered in the view which contains datatable. Below is the lazyloading code for search users.
public void getUsers(ActionEvent event) {
//few lines to get filterData
this.lazyUsers = new LazyDataModel<UserModel>() {
private static final long serialVersionUID = 1L;
#Override
public List<UserModel> load(int first, int pageSize, String sortField, SortOrder sortOrder,
Map<String, Object> filters) {
filterObject.setStartCount(new Long(first));
filterObject.setCountPerPage(new Long(pageSize));
List<UserModel> list = userService.getUsers(filterObject);
if (list != null)
this.setRowCount(list.get(0).getTotalNumberOfRecords().intValue());
RequestContext context = RequestContext.getCurrentInstance();
if(context!=null)
context.addCallbackParam("totalRecords", this.getRowCount());
return list;
}
};
}
and here's my table view.
<p:outputPanel id="users" autoUpdate="true">
<p:outputPanel rendered="#{users.displayusers}">
<h5 class="title">
<h:outputText value="#{msg.header_title}"></h:outputText>
</h5>
<p:dataTable id="userTable" lazy="true" paginator="true"
rows="2"
emptyMessage="#{msg.emtpymsg}"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="2,4,5"
rendered="#{null != users.lazyUsers && not empty users.lazyUsers }"
value="#{users.lazyUsers}" var="user"
rowIndexVar="userRow">
<p:column headerText="#{msg.Name}">
<h:outputLabel class="tdRow" value="#{user.name}" />
</p:column>
<p:column headerText="#{msg.Phone}">
<h:outputLabel class="tdRow" value="#{user.phone}" />
</p:commandLink>
</p:column>
<p:column headerText="#{msg.Address}">
<h:outputLabel class="tdRow" value="#{user.address}" />
</p:column>
<p:column headerText="#{msg.Email}">
<h:outputLabel class="tdRow" value="#{user.email}" />
</p:column>
</p:dataTable>
</p:outputPanel>
</p:outputPanel>
Everything renders when search happens but then when I paginate it searches for the next page data, and gets the next page data, but it renders it as plain html removing the datatable. On inspection of html, I can only see tr,td as response from server in network tab, and only contents within it are rendered directly into div. The datatable is not preserverd. Could anyone please let me know what's happening here.
I also tried to capture page event within datatable and added update value as
<p:ajax event="page" update="userContainer:userTable"></p:ajax>
but again it did not help. Hope to find some help.
Update
I noticed, this happens for any ajax operation through datatables, like, filtering, sorting, rowsperpage changed etc., Is there any way to identify on exactly what's wrong with this?
You change the value of rendered attribute. Try to encapsulate the dataTable ino another component, and re-render this outer component.
Also could be helpful if you place a dummy table in the template, that is always rendered, EG:
<p:dataTable disabled="true" />
This will make sure all the dataTable needed libraries are loaded at first load of your page...
The solution for this problem was very simple infact.
I had to keep <p:ajax event="page" update="userContainer:userTable"></p:ajax> and rather than update, I had to use process and also with ignoreAutoUpdate="true"
<p:ajax event="page" ignoreAutoUpdate="true" process="userContainer:userTable"></p:ajax>
That fixed the issue. Hope this will be useful to someone in future.
I have a need to display a list of Strings on a page, which a user will need to be able to add, edit, and delete entries. I figured I would use a DataTable to accomplish this.
The page appears to work properly - values are displayed in the DataTable, rows are deleted when the Delete icon is clicked, and rows are added when the Add button is clicked. However, when engaging the RowEditor by clicking the pencil icon, changes are never reflected when clicking the checkmark; the value of the row just goes back to being blank.
Here is a GIF showing the problem happening - http://imgur.com/a/dxlht
I've copied the majority of the DataTable markup from other pages in my project, which all work properly. The only difference I can see here is that this is a DataTable of Strings, not a complex object. Does this affect the "input" facet of the RowEditor when the value of the InputText is just a simple String?
Here is the DataTable markup:
<h:form>
<p:dataTable id="configTable" value="#{bean.configs}" var="config"
editable="true" editMode="row" emptyMessage="No entries exist.">
<p:column>
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{config}" /></f:facet>
<f:facet name="input"><p:inputText value="#{config}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column>
<p:rowEditor />
</p:column>
<p:column>
<p:commandLink update="configTable" styleClass="ui-icon ui-icon-trash" process="#this"
actionListener="#{bean.removeEntry(config)}" />
</p:column>
<f:facet name="footer">
<p:commandButton value="Add Entry" update="configTable" icon="ui-icon-plus" style="float:right;" process="#this"
actionListener="#{bean.addEntry()}" />
</f:facet>
</p:dataTable>
</h:form>
Here is the relevant bean code:
private List<String> configs;
public List<String> getConfigs() {
return this.configs;
}
public void setConfigs(List<String> configs) {
this.configs = configs;
}
public void removeEntry(String entry) {
this.configs.remove(entry);
}
public void addEntry() {
this.configs.add("");
}
I am using PrimeFaces 5.3/JSF 2.0.
Please note that when you press the check mark (to finish editing a row) JSF calls the setter method of whatever class your table rows are.
String class doesn't have a setter method, thus you will need to create a wrapper class with just one field (with getter and setter) and change your configs object to a List of yourClass objects.
I am having difficulty re-rendering a PrimeFaces Datatable once a cell has been edited. Changing the value in one cell may change entries in the other cells, hence the need to refresh the entire table.
Here's the JSF page:
<h:form id="testForm">
<p:outputPanel id="testContainer">
<p:dataTable id="testTable" value="#{tableBean.data}" var="entry" editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
<p:column headerText="Col1">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{entry.col1}" /></f:facet>
<f:facet name="input"><p:inputText value="#{entry.col1}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Col2">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{entry.col2}" /></f:facet>
<f:facet name="input"><p:inputText value="#{entry.col2}" /></f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
<p:commandButton id="refreshButton" value="Redisplay" update="testContainer" />
</p:outputPanel>
</h:form>
And here's the backing bean:
#ManagedBean(name = "tableBean", eager = false)
#ViewScoped
public class TableBean {
public TableBean() {
RowData entry = new RowData("a1", "b1");
entries.add(entry);
entry = new RowData("a2", "b2");
entries.add(entry);
entry = new RowData("a3", "b3");
entries.add(entry);
}
public class RowData {
private String col1;
private String col2;
public RowData(String col1, String col2) {
this.col1 = col1;
this.col2 = col2;
}
public String getCol1() {
return col1;
}
public void setCol1(String col1) {
this.col1 = col1;
}
public String getCol2() {
return col2;
}
public void setCol2(String col2) {
this.col2 = col2;
}
}
private ArrayList<RowData> entries = new ArrayList<RowData>();
public List<RowData> getData() {
return entries;
}
public void onCellEdit(CellEditEvent event) {
entries.get(event.getRowIndex()).setCol1("Dummy Col 1");
entries.get(event.getRowIndex()).setCol2("Dummy Col 2");
}
}
When including update=":testForm:testContainer" within the cellEdit AJAX event, changing a cell value deletes the datatable on screen and only renders the cell content (along with the button) -- I do not understand why this is. When the update attribute is not specified, the table remains on screen with the active cell updated, but none of the other cells are updated (as to be expected).
The desired behaviour can be achieved (in a non-automated way) by not specifying the update attribute within the AJAX cellEdit event and clicking the Redisplay button after editing a cell's value. How can I achieve this in an automated way, and why does the update attribute not work as I expect?
I am using PrimeFaces 4.0.
The rowEdit and cellEdit events does by design inside the table not update/re-render anything else than the current row, even not when explicitly specified in update attribute. It's the consequence of PrimeFaces' a bit overzealous attempt to minimize the response size. This makes sense in most of the cases, but not in specifically your case. It's worth an issue report.
In the meanwhile, until they fix this behavior, your best bet is using <p:remoteCommand> to invoke the desired listener method and perform a full update of the table.
Rewrite
<p:dataTable ...>
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
...
</p:dataTable>
to
<p:remoteCommand name="onCellEdit" action="#{tableBean.onCellEdit}" update="testContainer" />
<p:dataTable ...>
<p:ajax event="cellEdit" oncomplete="onCellEdit()" />
...
</p:dataTable>
The BaLusC solution has not worked directly for me. The onCellEdit needs a CellEditEvent as param. My workaround is as following:
<p:remoteCommand name="onCellEdit" update="testContainer" />
<p:dataTable ...>
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" oncomplete="onCellEdit()" />
...
</p:dataTable>
If none of the solutions worked for you, this worked for me
<p:dataTable ... id="theId" widgetVar="theWidget" ...>
<p:ajax event="rowEdit" listener="#{...}"
oncomplete="PF('theWidget').filter()"/>
....
I'm calling the filter method on the PF widget on ajax complete, any method that does a "reload" of the table should work, I used filter because my table had column filters.
I tested your code. First I moved p:commandButton out of p:outputPanel. Here is modified code:
<h:form id="testForm">
<p:outputPanel id="testContainer">
<p:dataTable id="testTable" value="#{tableBean.data}" var="entry" editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
(...)
</p:dataTable>
</p:outputPanel>
<p:commandButton id="refreshButton" value="Redisplay" update="testContainer" />
</h:form>
I think this code doesn't work correctly. if you change anything in table, the p:ajax every time render full table. So, the program load basic data from TableBean constructor and deleted new data.
If I omit your p:ajax code there is not disapears any new data from screen. The refreshButton p:commandButton work correctly.
When including update=":testForm:testContainer" within the cellEdit
AJAX event, changing a cell value deletes the datatable on screen and
only renders the cell content (along with the button) -- I do not
understand why this is.
I think it is bad design add update=":testForm:testContainer" to ajax, because it's update your outputPanel more than as exepted (first time work correctly, second time couldn't edit cell, because the program update to many times table).
I don't know what is your goal. If you want render table without a commandButton, then could you specify one javascript event or p:message and this disappear you can render table.
I think if you omit update in p:ajax or specify update of one p:message, and move p.commandButton out of testContainer your code start work correctly.
After 5 years, this problem still exists. Unfortunately, while Baukes solution is extremly helpful and includes important insights it's still incomplete, as ltlBeBoy already pointed out in his comment. Subsequent edits without change lead to an inconsistent table state, where no more edits are possible. The reason is, that the oncomplete remote update comes after the edit mode of the new cell is already activated. So the edit mode of the new cell is destroyed by the update. However, the update can't be done in Ajax listener tableBean#onCellEdit, as this would display the table erroneously with one cell only.
The solution is, to execute the update in the remote commands listener and only, if a change happend. So, in tableBean you implement a programmatic update, a remote listener and a flag that indicates change:
public static void update(String id) {
PrimeFaces pf = PrimeFaces.current(); //RequestContext.getCurrentInstance() for <PF 6.2
if(pf.isAjaxRequest()) pf.ajax().update(id);
}
/** Whether onCellEdit changed the value */
boolean onCellEditChange;
public void onCellEditRemote() {
if(!onCellEditChange) update("testContainer");
}
public void onCellEdit(CellEditEvent event) {
... onCellEditChange= /*Change happend*/ ...
}
The remote command has no update attribute any more:
<p:remoteCommand name="onCellEdit" actionListener="#{tabelBean.onCellEditRemote}"/>
try using process
<p:remoteCommand name="onCellEdit" update="testContainer" process="#this" />
<p:dataTable ...>
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" oncomplete="onCellEdit()" process="#this" />
...
</p:dataTable>
This is my first post ever in here. As ltlBeBoy mentioned, BalusC's solution works only if the cell editing is done with an enter key hit.
None of the other suggestions listed in here worked for me.
In my case, I just wanted to update a specific row (that has each column's average) in the table on cellEdit event. I'm posting this in case if someone out there is looking for a solution: I managed to achieve this by separating that row in a second datatable right below the main one. Here's the code:
<pf:ajax event="cellEdit"
listener="#{newAgentMetricBacking.onCellEdit}"
update="c21413" />
<pf:dataTable id="c21413"
styleClass="noHeader"
value="">
<pf:column>
<h:outputText value="#{bundle.TeamAverage}"/>
</pf:column>
<pf:columns columnIndexVar="j"
value="#{newAgentMetricBacking.averageArray}"
var="avg">
<h:outputText value="#{newAgentMetricBacking.
averageArray[j]}"/>
</pf:columns>
</pf:dataTable>
Otherwise, as of today, I couldn't find a better solution for updating either the whole table or a specific row specifically upon success of cellEdit event.
Cheers!
I am having difficulty re-rendering a PrimeFaces Datatable once a cell has been edited. Changing the value in one cell may change entries in the other cells, hence the need to refresh the entire table.
Here's the JSF page:
<h:form id="testForm">
<p:outputPanel id="testContainer">
<p:dataTable id="testTable" value="#{tableBean.data}" var="entry" editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
<p:column headerText="Col1">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{entry.col1}" /></f:facet>
<f:facet name="input"><p:inputText value="#{entry.col1}" /></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Col2">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{entry.col2}" /></f:facet>
<f:facet name="input"><p:inputText value="#{entry.col2}" /></f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
<p:commandButton id="refreshButton" value="Redisplay" update="testContainer" />
</p:outputPanel>
</h:form>
And here's the backing bean:
#ManagedBean(name = "tableBean", eager = false)
#ViewScoped
public class TableBean {
public TableBean() {
RowData entry = new RowData("a1", "b1");
entries.add(entry);
entry = new RowData("a2", "b2");
entries.add(entry);
entry = new RowData("a3", "b3");
entries.add(entry);
}
public class RowData {
private String col1;
private String col2;
public RowData(String col1, String col2) {
this.col1 = col1;
this.col2 = col2;
}
public String getCol1() {
return col1;
}
public void setCol1(String col1) {
this.col1 = col1;
}
public String getCol2() {
return col2;
}
public void setCol2(String col2) {
this.col2 = col2;
}
}
private ArrayList<RowData> entries = new ArrayList<RowData>();
public List<RowData> getData() {
return entries;
}
public void onCellEdit(CellEditEvent event) {
entries.get(event.getRowIndex()).setCol1("Dummy Col 1");
entries.get(event.getRowIndex()).setCol2("Dummy Col 2");
}
}
When including update=":testForm:testContainer" within the cellEdit AJAX event, changing a cell value deletes the datatable on screen and only renders the cell content (along with the button) -- I do not understand why this is. When the update attribute is not specified, the table remains on screen with the active cell updated, but none of the other cells are updated (as to be expected).
The desired behaviour can be achieved (in a non-automated way) by not specifying the update attribute within the AJAX cellEdit event and clicking the Redisplay button after editing a cell's value. How can I achieve this in an automated way, and why does the update attribute not work as I expect?
I am using PrimeFaces 4.0.
The rowEdit and cellEdit events does by design inside the table not update/re-render anything else than the current row, even not when explicitly specified in update attribute. It's the consequence of PrimeFaces' a bit overzealous attempt to minimize the response size. This makes sense in most of the cases, but not in specifically your case. It's worth an issue report.
In the meanwhile, until they fix this behavior, your best bet is using <p:remoteCommand> to invoke the desired listener method and perform a full update of the table.
Rewrite
<p:dataTable ...>
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
...
</p:dataTable>
to
<p:remoteCommand name="onCellEdit" action="#{tableBean.onCellEdit}" update="testContainer" />
<p:dataTable ...>
<p:ajax event="cellEdit" oncomplete="onCellEdit()" />
...
</p:dataTable>
The BaLusC solution has not worked directly for me. The onCellEdit needs a CellEditEvent as param. My workaround is as following:
<p:remoteCommand name="onCellEdit" update="testContainer" />
<p:dataTable ...>
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" oncomplete="onCellEdit()" />
...
</p:dataTable>
If none of the solutions worked for you, this worked for me
<p:dataTable ... id="theId" widgetVar="theWidget" ...>
<p:ajax event="rowEdit" listener="#{...}"
oncomplete="PF('theWidget').filter()"/>
....
I'm calling the filter method on the PF widget on ajax complete, any method that does a "reload" of the table should work, I used filter because my table had column filters.
I tested your code. First I moved p:commandButton out of p:outputPanel. Here is modified code:
<h:form id="testForm">
<p:outputPanel id="testContainer">
<p:dataTable id="testTable" value="#{tableBean.data}" var="entry" editable="true" editMode="cell">
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
(...)
</p:dataTable>
</p:outputPanel>
<p:commandButton id="refreshButton" value="Redisplay" update="testContainer" />
</h:form>
I think this code doesn't work correctly. if you change anything in table, the p:ajax every time render full table. So, the program load basic data from TableBean constructor and deleted new data.
If I omit your p:ajax code there is not disapears any new data from screen. The refreshButton p:commandButton work correctly.
When including update=":testForm:testContainer" within the cellEdit
AJAX event, changing a cell value deletes the datatable on screen and
only renders the cell content (along with the button) -- I do not
understand why this is.
I think it is bad design add update=":testForm:testContainer" to ajax, because it's update your outputPanel more than as exepted (first time work correctly, second time couldn't edit cell, because the program update to many times table).
I don't know what is your goal. If you want render table without a commandButton, then could you specify one javascript event or p:message and this disappear you can render table.
I think if you omit update in p:ajax or specify update of one p:message, and move p.commandButton out of testContainer your code start work correctly.
After 5 years, this problem still exists. Unfortunately, while Baukes solution is extremly helpful and includes important insights it's still incomplete, as ltlBeBoy already pointed out in his comment. Subsequent edits without change lead to an inconsistent table state, where no more edits are possible. The reason is, that the oncomplete remote update comes after the edit mode of the new cell is already activated. So the edit mode of the new cell is destroyed by the update. However, the update can't be done in Ajax listener tableBean#onCellEdit, as this would display the table erroneously with one cell only.
The solution is, to execute the update in the remote commands listener and only, if a change happend. So, in tableBean you implement a programmatic update, a remote listener and a flag that indicates change:
public static void update(String id) {
PrimeFaces pf = PrimeFaces.current(); //RequestContext.getCurrentInstance() for <PF 6.2
if(pf.isAjaxRequest()) pf.ajax().update(id);
}
/** Whether onCellEdit changed the value */
boolean onCellEditChange;
public void onCellEditRemote() {
if(!onCellEditChange) update("testContainer");
}
public void onCellEdit(CellEditEvent event) {
... onCellEditChange= /*Change happend*/ ...
}
The remote command has no update attribute any more:
<p:remoteCommand name="onCellEdit" actionListener="#{tabelBean.onCellEditRemote}"/>
try using process
<p:remoteCommand name="onCellEdit" update="testContainer" process="#this" />
<p:dataTable ...>
<p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" oncomplete="onCellEdit()" process="#this" />
...
</p:dataTable>
This is my first post ever in here. As ltlBeBoy mentioned, BalusC's solution works only if the cell editing is done with an enter key hit.
None of the other suggestions listed in here worked for me.
In my case, I just wanted to update a specific row (that has each column's average) in the table on cellEdit event. I'm posting this in case if someone out there is looking for a solution: I managed to achieve this by separating that row in a second datatable right below the main one. Here's the code:
<pf:ajax event="cellEdit"
listener="#{newAgentMetricBacking.onCellEdit}"
update="c21413" />
<pf:dataTable id="c21413"
styleClass="noHeader"
value="">
<pf:column>
<h:outputText value="#{bundle.TeamAverage}"/>
</pf:column>
<pf:columns columnIndexVar="j"
value="#{newAgentMetricBacking.averageArray}"
var="avg">
<h:outputText value="#{newAgentMetricBacking.
averageArray[j]}"/>
</pf:columns>
</pf:dataTable>
Otherwise, as of today, I couldn't find a better solution for updating either the whole table or a specific row specifically upon success of cellEdit event.
Cheers!
I have a JSF datatable with a bunch of rows, with each row having a selectOneMenu inside of it like this:
<h:form
<h:dataTable id="myTable"
binding="#{myBean.dataTable}"
value="#{myBean.dataTableRows}" var="row"
first="0" rows="0" dir="LTR" frame="hsides" rules="all">
<h:column>
<f:facet name="header">
<h:outputText value="Sample Name" />
</f:facet>
<h:outputText value="#{row.sampleName}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Role" />
</f:facet>
<h:selectOneMenu value="#{row.role}"
id="roleInput">
<f:selectItems value="#{myBean.allRoles}" />
</h:selectOneMenu>
</h:column>
</h:dataTable>
<h:commandButton value="Save" action="#{myBean.save}" />
</h:form>
However, I can't seem to figure out how get the selected role out of each row in the save method. In other words, I want to save each row's value. I saw this article, which explains how to save an input text box:
http://balusc.blogspot.com/2006/06/using-datatables.html#EditableDatatable
but it doesn't seem to apply to the h:selectOneMenu case. Does anyone have any example code that does this?
Thanks!
I see your table has binding to your bean. In your bean you can use the getDataTable() method and access it. Java doc says:
public Object getRowData()
Return the data object representing the data for the currently selected row index, if any.
So if you do your code like:
List<String> selectedRowData = (List<String>) getDataTable().getRowData()
You can then access all the fields the user has chosen. Im using this in my own project and its working. The only difference is that Im casting to my own type instead of List<String>
There are no obvious errors in the form - if your save method is not being invoked, try adding a messages tag to your form to help track down the source of the problem. It would help if you posted a sample bean that reproduces the problem and state the JSF implementation and version you are using.