Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update specific row in Primefaces datatable

Tags:

primefaces

Primefaces 3.5, Mojarra 2.1.14. This is my PF datatable, it contains one non-editable boolean column named 'automatic', and editable 'label' column:

<p:dataTable value="#{bean.contents}" paginator="true" var="row" 
  editable="true" editMode="cell" rows="25" rowsPerPageTemplate="10,25,50" id="list">
    <p:column>
        <f:facet name="header"><h:outputText value="header1" /></f:facet>
        <p:selectBooleanCheckbox value="#{row.automatic}" disabled="true" id="isAutomatic"></p:selectBooleanCheckbox>
    </p:column>
    <p:column>
        <f:facet name="header"><h:outputText value="header2" /></f:facet>
        <p:cellEditor>
            <f:facet name="output">
                <h:outputText value="#{row.label}"></h:outputText>
            </f:facet>
            <f:facet name="input">
                <p:inputText value="#{row.label}"></p:inputText>
            </f:facet>
        </p:cellEditor>
    </p:column>
    <p:ajax event="cellEdit" process="@this" listener="#{myBean.onEditLabel}" update="isAutomatic"/>
</p:dataTable>

Cell edit event listener:

public void onEditLabel(CellEditEvent event) {
    Object oldValue = event.getOldValue();
    Object newValue = event.getNewValue();

    if(newValue != null && !newValue.equals(oldValue)) {
        DataTable s = (DataTable) event.getSource();
        MyEntity d = (MyEntity) s.getRowData();
        try {
            d.setAutomatic(false);
            myDAO.save(d);
            addMessage("Change saved!");
        } catch (Exception ex) {
            addErrorMessage("Label could not be saved!");
            getFacesContext().validationFailed();
        }
    }
}   

The cell editor works, sends data to listener, and it is correctly persisted to the database. The 'automatic' flag is also cleared by cell edit event listener, and gets correctly persisted to the database. The problem is that 'automatic' checkbox is not updated on the client.

I also tried

    <p:ajax event="cellEdit" process="@this" listener="#{myBean.onEditLabel}" update="list"/>

which correctly updated the checkbox, but also causes focus to be lost, and wastes bandwidth.

How can I update just a specific cell after cellEdit event is fired?

like image 742
rootkit Avatar asked Mar 06 '13 20:03

rootkit


2 Answers

You p:ajax tag is inside p:dataTable no in some specific row or column, so you cent so easy update some relative component id. You can with help of RequestContext update specific component in cell. So, remove update from p:ajax and add this to your onEditLabel method:

RequestContext.getCurrentInstance().update(
  s.getClientId(FacesContext.getCurrentInstance()) +
  ":" + event.getRowIndex() +
  ":isAutomatic"
);

As you can see, id of component inside cell has row number before id you assigned.

like image 63
partlov Avatar answered Oct 21 '22 08:10

partlov


I believe you can solve this without having to know the details of the ID of the component you wish to update. You can pass it as a parameter to the bean.

First, bind the component you wish to update. You don't actual need a bean to which this component is bound to. You just need to define some value which you can use to identify this component later in your JSF. So in your case, you would do something like:

<p:selectBooleanCheckbox binding="#{isAutomaticComponent}" value="#{row.automatic}" disabled="true" id="isAutomatic"></p:selectBooleanCheckbox>

Now access the component when you do your update. ie:

<p:ajax event="cellEdit" process="@this" listener="#{myBean.onEditLabel(isAutomaticComponent.clientId)}" />

Now you can update the component from your cellEdit event method without knowing the contents of the ID. ie:

public void onEditLabel(CellEditEvent event, String idOfComponentToUpdate) {
...
RequestContext.getCurrentInstance().update(idOfComponentToUpdate);
...
like image 24
Todd Thiessen Avatar answered Oct 21 '22 07:10

Todd Thiessen