Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

primefaces datatable rowedit not updating cell element

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

like image 585
roel Avatar asked Jan 03 '14 10:01

roel


3 Answers

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);

    // ...
}
like image 90
BalusC Avatar answered Nov 19 '22 15:11

BalusC


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.

like image 28
Neverland14 Avatar answered Nov 19 '22 16:11

Neverland14


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.

like image 1
snakedog Avatar answered Nov 19 '22 15:11

snakedog