I have a couple of nested tables as the code shows. When a user click a checkbox, the ajax call is sent to the server and then back to the client. If the process in the server is working correctly, the clicked operation row is removed from the html code using jquery when it gets the callback. Then when user tries to delete another row in the same operations table, the values that are sent to the server are NOT correct. The call sends next row values: #{trade.murexId}, #{operation.id} and #{operation.operation}, but NOT the right ones. Javascript and jquery callback functions are working properly. I'm using last version of Mojarra. Why this happened? and How can I solve it?
HTML:
<table id="trades">
<th class="image_cell"></th>
<th>Murex Id</th>
<th>Type</th>
<th>Portfolio</th>
<th>Log</th>
<ui:repeat var="trade" value="#{controller.errorTrades}">
<h:form>
<tr class="trade error">
<td class="image_cell error"><h:graphicImage styleClass="expandable" url="resources/images/plus.png"></h:graphicImage></td>
<td id="murex_id" class="error">#{trade.murexId}</td>
<td id="type" class="error">#{trade.type}</td>
<td class="error">#{trade.portfolio}</td>
<td class="error">
<h:commandButton image="resources/images/log_big.jpg" action="#{controller.onLogTrade(trade.murexId)}">
<f:ajax render="log_big" />
</h:commandButton>
<h:panelGroup id="log_big">
<h:outputScript rendered="#{not empty controller.result}">
onLogProcess("#{controller.result}");
</h:outputScript>
</h:panelGroup>
</td>
</tr>
<tr class="operations">
<td id="#{trade.murexId}" class="operation_row" colspan="5">
<table id="operations">
<tr class="header">
<th class="empty_cell"></th>
<th class="operation_cell">Operation</th>
<th>Murex Status</th>
<th>GBO Status</th>
<th>GBO Id</th>
<th>OPICS Id</th>
<th>Time Transaction</th>
<th>Comment</th>
<th id="delete">Delete</th>
<th>Log</th>
</tr>
<ui:repeat var="operation" value="#{trade.operationsSortDescList}" varStatus="status">
<tr class="operation">
<th class="empty_cell"></th>
<td id="operation" class="operation_cell color">#{operation.operation}</td>
<td class="color">#{operation.statusMurex}</td>
<td id="status_gbo" class="color">#{operation.statusGbo}</td>
<td id="gbo_id" class="color">#{operation.gboId}</td>
<td id="opics_id" class="color">#{operation.opicsId}</td>
<td class="color">#{operation.datetimeToString}</td>
<td class="color">#{operation.coment}</td>
<td class="color checkbox">
<h:selectBooleanCheckbox>
<f:ajax execute="@form" event="click" listener="#{controller.onDelete}" onevent="onDeleteProcess" />
<f:attribute name="murexId" value="#{trade.murexId}" />
<f:attribute name="operationId" value="#{operation.id}" />
<f:attribute name="operation" value="#{operation.operation}" />
</h:selectBooleanCheckbox>
</td>
<td class="color log">
<h:commandButton image="resources/images/log_small.jpg" action="#{controller.onLogOperation(operation)}">
<f:ajax execute="@form" render="small_log" />
</h:commandButton>
<h:panelGroup id="small_log">
<h:outputScript rendered="#{not empty controller.result}">
onLogProcess("#{controller.result}");
</h:outputScript>
</h:panelGroup>
</td>
</tr>
</ui:repeat>
</table>
</td>
</tr>
</h:form>
</ui:repeat>
</table>
Thanks in advance!
REEDIT:
I changed h:selectBooleanCheckbox to h:commandButton.
View:
<table id="operations">
<tr class="header">
<th class="empty_cell"></th>
<th class="operation_cell">Operation</th>
<th>Murex Status</th>
<th>GBO Status</th>
<th>GBO Id</th>
<th>OPICS Id</th>
<th>Time Transaction</th>
<th>Comment</th>
<th id="delete">Delete</th>
<th>Log</th>
</tr>
<ui:repeat var="operation" value="#{trade.operationsSortDescList}" varStatus="status">
<tr class="operation">
<th class="empty_cell"></th>
<td id="operation" class="operation_cell color">#{operation.operation}</td>
<td class="color">#{operation.statusMurex}</td>
<td id="status_gbo" class="color">#{operation.statusGbo}</td>
<td id="gbo_id" class="color">#{operation.gboId}</td>
<td id="opics_id" class="color">#{operation.opicsId}</td>
<td class="color">#{operation.datetimeToString}</td>
<td class="color">#{operation.coment}</td>
<td class="color checkbox">
<h:commandButton image="resources/images/log_small.jpg" action="#{controller.onDelete(operation)}">
<f:ajax execute="@form" render="small_log" onevent="onDeleteProcess" />
</h:commandButton>
</td>
<td class="color log">
<h:commandButton image="resources/images/log_small.jpg" action="#{controller.onLogOperation(operation)}">
<f:ajax execute="@form" render="small_log" />
</h:commandButton>
<h:panelGroup id="small_log">
<h:outputScript rendered="#{not empty controller.result}">
onLogProcess("#{controller.result}");
</h:outputScript>
</h:panelGroup>
</td>
</tr>
</ui:repeat>
</table>
Controller:
public void onDelete(Operation operation)
{
Trade trade = operation.getTrade();
Boolean result = false;
try {
if (trade.getOperations().size() == 1) {
result = Modelo.deleteTrade(trade);
if (result)
this.trades.remove(trade);
} else {
result = Modelo.deleteOperation(operation);
if (result)
trade.getOperations().remove(operation);
}
} catch(Exception ex) {
ConfigUtil.LOGGER.error(ex);
}
}
When I delete an operation, it's the problem. No because of jquery. I'm sure about that because I tested it. When I delete an operation and click the next operation, it sends to the server the wrong operation. Any idea why this is happening?
Thanks!
Firstly I would recomend using datatable
instead of raw html table . Datatable will generate similar html any way but the benifit is that you will have access to server component tree.
You do not really need to use jQuery
but I will just leave to this because you can use it if you must but in that case use change
<table id="trades">
to
<table id="trades" jsfc="h:dataTable binding="#{controller.dataTable}">
assuming h
is your namespace reference for JSF html tag lib.
Declare private javax.faces.component.html.HtmlDataTable dataTable ;
in your managed bean which seams to be controller
.
Now in your code for listener="#{controller.onDelete}"
you will have to remove that from server side before returning.
While this will achieve it does seems hacky and you are better of not using jQuery
and just do a re-render the datatable not any more expensive than other option..
You might find this link helpful.
That's probably because you are changing the elements in your view without the server side knowing about it.
Try not to use JQuery directly for changing the DOM, use the JSF2 Ajax funcionalities instead, with render
and rerender
attributes.
See the answer to this question