Prerequisites:
JSF 2.1
Primefaces 5.2
Glassfish 3.1
Story:
I got a datatable displaying some editable values.
The amount of columns is dynamic.
In the same form is a button calling a save-action of my bean to save all edited data.
The function it self is working perfectly fine
Implementation:
<p:dataTable id="dataTable" scrollable="true"
widgetVar="wigVardataTable"
value="#{myBean.dataList}"
var="data"
editable="true"
editMode="cell"
rowKey="rowkey">
<p:columns var="col"
value="#{myModel.columnList}"
style="font-size: 12px">
<f:facet name="header">
<h:outputText
value="#{col.header}" />
</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText
value="#{myModel.getValueForTableCell(data, col).value}" />
</f:facet>
<f:facet name="input">
<p:inputText
id="inputTxt"
value="#{myModel.getValueForTableCell(data, col).value}"
style="width:100%">
</p:inputText>
</f:facet>
</p:cellEditor>
</p:columns>
</p:dataTable>
Problem:
When pressing the save button while a table cell is being edited and didn't loose its focus yet, the new value inside the inputtext of the tablecell won't be written back into my bean and due to that won't be saved.
Question:
How can i write back the data into my backing bean, before the button action is executed?
This behavior is caused by wrong ordering of ajax events. When the command button is invoked while having a cell editor open, then the ajax event of the command button is fired before the ajax event of the cell edit.
We'd thus like to swap around them. Without editing the PrimeFaces source code, you could achieve this by explicitly invoking saveCell() function of the <p:dataTable> widget when there's a cell editor open.
So, given a
<h:form>
<p:dataTable ... widgetVar="wigVardataTable" />
<p:commandButton ... />
</h:form>
you can achieve the desired behavior by adding the below onclick to the <p:commandButton>:
onclick="var d=PF('wigVardataTable'), c=d.jq.find('td:has(.ui-cell-editor-input:visible)'); if(c.length)d.saveCell(c)"
Basically, it first finds the cell with an open cell editor and then invokes saveCell() on it.
Another, less elegant, way is explicitly invoking showCellEditor() function of the <p:dataTable> widget without passing the expected target cell in a try-catch block where the exception is ignored.
onclick="try{PF('wigVardataTable').showCellEditor()}catch(ignore){}"
It will save any opened cell first and later throw an error that no new target cell was specified as argument, but that could be ignored as shown above.
Noted should be that this all works regardless of whether you use <p:columns> or <p:column>, and also regardless of whether you use a normal model or an overcomplicated model ;) This trick is tested on both your PrimeFaces 5.2 version and the current PrimeFaces 6.0 version.
Here is a generic solution inspired by BalusC answer if you have other datatables with cell editMode :
<script type="application/javascript">
function saveAllCellsBeforeSubmit() {
for (var widgetName in PrimeFaces.widgets) {
if (PrimeFaces.widgets[widgetName].hasOwnProperty('cfg') && PrimeFaces.widgets[widgetName].cfg.hasOwnProperty('editMode') && PrimeFaces.widgets[widgetName].cfg.editMode === 'cell') {
var d = PF(widgetName);
var c = d.jq.find('td:has(.ui-cell-editor-input:visible)');
if (c.length) {
d.saveCell(c);
}
}
}
}
</script>
Related
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!
This question already has an answer here:
How to decrease request payload of p:ajax during e.g. p:dataTable pagination
(1 answer)
Closed 7 years ago.
I have a datatable in which each row has 24 hour input fields in it. At one point of time there are more than 1000 editable input fields. I noticed that while using p:cellEditor during ajax calls primefaces is submitting the entire datatable. How can I avoid that?
Please find below the code that I have, and also find the comments on each important parts in them.
<!-- Fires the cellEdit event to trigger the validations to happen as user tabs out of the input box -->
<p:ajax event="cellEdit" listener="#{renderValidator.onCellEdit}" update=":#{p:component('globalMessages')}" process="#this" />
<p:column id="hour1" styleClass="col-right col-90">
<f:facet name="header">
<h:outputText value="1" escape="false"/>
</f:facet>
<p:cellEditor >
<f:facet name="output">
<h:outputText value="#{row.amount[0]}" escape="false">
<f:convertNumber maxFractionDigits="3" minFractionDigits="3" maxIntegerDigits="5" />
</h:outputText>
</f:facet>
<f:facet name="input">
<p:inputText id="hour1Input" value="#{row.amount[0]}" maxlength="10" size="10" readonly="#{row.readOnly}" onchange='PowerMeter.setPowerMeterChange()'
styleClass="col-right" valueChangeListener="#{row.setDirtyFlag(true)}" >
<!-- formats data the way its displayed -->
<f:convertNumber maxFractionDigits="3" minFractionDigits="3" maxIntegerDigits="5" />
<!-- validates the input value w.r.t a custom validator -->
<f:validator validatorId="hourlyValueValidator" for="hour1Input" />
<!-- javascript restricting user to input alpha numeric characters -->
<pe:keyFilter testFunction="return PowerMeter.isValidMWH(this, c);" />
</p:inputText>
</f:facet>
</p:cellEditor>
</p:column>
On Ajax requests, JSF sends the data for all input components in the form by default. Even if only one out of 100 components is executed in the partial lifecycle. With PrimeFaces you can alter this behavior by setting partialSubmit to true like this:
<p:ajax partialSubmit="true" event="cellEdit" process="#this"
listener="#{renderValidator.onCellEdit}"
update=":#{p:component('globalMessages')}"/>
Primefaces uses the PrimeFaces.ajax.AjaxUtils.send function to build Ajax requests. To determine what data need to be send to the server it uses jQuery find function and then serializeArray which is used to build a POST requests.
componentPostParams = jqProcess.find(':input').serializeArray();
Unfortunately when the liveScroll attribute is enabled for the <p:DataTable> and there is already a huge amount of data fetched it will process all input controls no matter if <p:cellEditor> have only one input facet visible.
To change this functionality I overrode PrimeFaces.ajax.AjaxUtils.send function in the below form
var pFacesSend = PrimeFaces.ajax.AjaxUtils.send;
PrimeFaces.ajax.AjaxUtils.send = function(cfg) {
if (myCase) {
// Custom send
} else {
pFacesSend(cfg);
}
};
And in myCase I changed additionally serialization from this:
componentPostParams = jqProcess.find(':input').serializeArray();
Into this:
if (!customSerializationCondition) {
componentPostParams = jqProcess.find(':input').serializeArray();
} else {
componentPostParams = jqProcess.find(':input').filter(function() {
return $(this).parent().css('display') !== 'none';
}).serializeArray();
}
This solution builds a POST request that only includes visible input fields and because of my editMode set to cell I have only one <input> visible.
It works for Primefaces v4.0 and should work whenever the input parent tag uses css display attribute to hide input facet in the editor.
I have a commandButton inside a DataTable. However the "action" isn't called when I click on it (same effect with an actionListener); I added logs at the beginning of the server action, and it never shows.
Please note that the button works fine when outside from the datalist.
Here is my code:
<h:form id="compSearchForm">
<p:dataTable var="competency" value="#{competencySearchBean.matchingCompetencies.toArray()}">
<p:column>
<f:facet name="header">
<h:outputLabel value="Title" />
</f:facet>
<h:outputText value="#{competency.title}" />
</p:column>
<p:column>
<p:commandButton value="Go" id="actionButton" action="#{myBean.doAction}" />
</p:column>
</p:dataTable>
</h:form>
Would you have any idea as to what the issue might be?
I added your button column code to an existing of mine along with a dummy method in by backing bean. The method is called correctly when I press the button it works correctly. Here is the code I added to my dataTable:
<p:column>
<p:commandButton value="Go" id="actionButton" action="#{tableBean.buttonAction()}" />
</p:column>
Here is the buttonAction method in my backing bean:
public void buttonAction()
{
int a = 0;
for(int i = 0; i < 100; i++)
a = i;
}
I put a breakpoint on this method, so I know it is getting called when I click the button.
I went a step further and used your datatable code (with my data source) and the method is still being called when I press the button. I don't know what development environment you are using, but if it has a debug mode put a breakpoint on your doAction method, and a few other strategic locations in your bean, then run your project in debug mode to see what is going on.
I think you have to change to:
<h:form id="compSearchForm">
<p:dataTable var="competency" value="#{competencySearchBean.matchingCompetencies.toArray()}">
<p:column>
<f:facet name="header">
<h:outputLabel value="Title" />
</f:facet>
<h:outputText value="#{competency.title}" />
</p:column>
</p:dataTable>
<p:commandButton value="Go" id="actionButton" action="#{myBean.doAction}" />
</h:form>
I don't think you can have the button inside the dataTable. Try this.
see this example - http://www.primefaces.org/showcase/ui/datatableRowSelectionByColumn.jsf
I think you must prefix the id with the form ID
see how it updates ":form:display" instead of only "display"
worked for me
I had the same problem and after trying different ways, I resolved it by initializing my List (the list that I use in the p:datatable) in the init method of the Bean.
With this form, the list goes to the page with some values.
Even when I put List<Paciente> myList = new ArrayList<Paciente>(); it didn't work.
I have to put some values in the list. That was the only way that resolved the problem.