I have a datatable with rowedit. One column of my table is a cell with a listbox in, the items of the listbox are dynamically retrieved (depending on the value in another cell) I use rowEditInit to set the selectedrow item. And I want to update the listbox to retrieve the correct values. This does not work. When I do
<p:ajax event="rowEditInit" listener="#{workOrderDetail.onEdit}" update="orderitemstable" />
Then when I click the pencil icon, the I can see the row switch to edit mode and retriving the listbox items. But it directly swithced back to non edit mode.
But when I do
<p:ajax event="rowEditInit" listener="#{workOrderDetail.onEdit}" update="rmactionenumid" />
Then clicking the pencil icon puts the row in edit mode, but no call is made to retrieve the listbox items. My gues is, it does not trigger the update on rmactionenumid.
Any ideas?
Roel
Here is my jsf code
<p:ajax event="rowEditInit" listener="#{workOrderDetail.onEdit}" update="rmactionenumid" />
<p:column >
<p:cellEditor>
<f:facet name="output">
<h:outputText id="rmactionenumidlabel" value="#{orderItem.rmActionRepr}" >
</h:outputText>
</f:facet>
<f:facet name="input">
<h:selectOneListbox id="rmactionenumid" value="#{orderItem.rmActionEnumId}" size="1" valueChangeListener="#{workOrderDetail.setActionRepr}">
<f:selectItems value="#{workOrderDetail.actionItems}"/>
<p:ajax event="change" update="partdiscount,labourdiscount,totalprice,:detail:wodetail:totals" execute="@this" />
</h:selectOneListbox>
</f:facet>
</p:cellEditor>
</p:column>
<p:column >
<p:rowEditor id="edit" />
</p:commandLink>
</p:column>
</p:dataTable>
and here is my java bean code
public List<SelectItem> getActionItems() throws MWSException {
ArrayList<SelectItem> actions = new ArrayList<SelectItem>();
if (getSelectedOrderItem() != null) {
ListManager lm = new ListManager(getWA().getMwsProxy());
MWSGenericMapList items = lm.nativeSearch(getWS().getUser(), HdfWebConstants.NS_VEHICLEPARTACTIONS, 0, 0, 200,
false, getSelectedOrderItem().getVehiclePartCode());
for (int i = 0; i < items.size(); i++) {
actions.add(new SelectItem(items.get(i).get("rmaction_enumid").toString(), items.get(i).get("rmaction")
.toString()));
}
}
return actions;
}
public void setSelectedOrderItem(IMWSOrderItem newSelectedOrderItem) throws MWSException {
this.selectedOrderItem = newSelectedOrderItem;
}
public void onEdit(RowEditEvent event) throws MWSException {
setSelectedOrderItem((IMWSOrderItem) event.getObject());
}
I'm using PF3.5
It fails because update="rmactionenumid"
is in this construct relative to the table itself, not to the current table row.
Basically, it's looking for a component with client ID formId:tableId:rmactionenumid
instead of e.g. the second row formId:tableId:1:rmactionenumid
. Technically, the <p:ajax>
should be placed inside the <p:column>
, but this won't work out for rowEditInit
event.
You'd need to compose your own update
client ID based on the UIData
component which is available as RowEditEvent
argument and add the composed client ID to PartialViewContext#getRenderIds()
.
So, remove the <p:ajax update>
and extend the onUpdate()
method as follows:
public void onEdit(RowEditEvent event) {
UIData table = (UIData) event.getComponent();
String updateClientId = table.getClientId() + ":" + table.getRowIndex() + ":rmactionenumid";
FacesContext.getCurrentInstance().getPartialViewContext().getRenderIds().add(updateClientId);
// ...
}
Along the lines of BalusC's answer:
Since you're using Primefaces 3.5 you could alternatively make use of its utility classes ComponentUtils and RequestContext:
String actId = ComponentUtils.findComponentClientId( "rmactionenumid" );
RequestContext.getCurrentInstance().update( actId );
will do the same as the snippet posted by BalusC.
OMG it took me a long time to figure this one out. BalusC is as always dead on the money but the thing that escaped me was that updating a Datatable does not update all its children as I expected. Updating the table does in fact update the rows (deleted rows in the underlying model disappear) and reorder rows if the underlying model has been reordered, but values in outputText widgets inside CellEditor containers are not updated, except for the one edited, unless you supply a <p:ajax />
tag to those you want to update, which in my case was all of them. I am guessing there was a design assumption that when a CellEditor initiated an Ajax call, the Datatable parent would only update the child cell edited. I've never understood why a CellEditor needs both an InputText and an OutputText contained in order to work.
This led to horrendous problems for me when multiple users concurrently edited the same Datatable in different sessions. UserA would make an edit and get a correctly updated table, potentially with the rows in a different order. Then UserB, whose Datatable was now out of date, would make an edit, and the edit would get persisted to the database correctly (because the row had a unique, hidden ID) but the edit would go to the wrong row in the Datatable (but the correct column), and UserB, even after update, would not see UserA's change in a different cell. Once I put the <p:ajax update="datatableID" />
tag in the inputText body it worked properly. I still had concurrency issues which I had to solve separately, but at least the Datatable was correct after edits.
BalusC, if you are out there, please correct my bad assumptions here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With