Search code examples
primefacesjsf-2datatablelazy-loading

RowKey of DataTable is null when calling onCellEdit


I have a Primefaces 6.0 DataTable working with a LazyDataModel bean. After I changed to the lazy implementation, the cell edition stopped working. The reason for that is whenever I call my onCellEdit method, and try to get the clicked row contents by calling event.getRowkey() , I get a null object. As per Primefaces Documentation I'm have a rowKey attribute to bind the tuple with the bean value, but it doesn't seems to work.

EDIT: I can update the value now, but the dataTable doesn't reload the cell UiElement. To see the changes i have to F5 the page.

Here is my ata.xhtml DATATABLE(Sanitized)

<p:tabView id="tab" value="#{setorMB.listaSetor}" var="tabView" 
    activeIndex="#{ataGerencialMB.activeTabIndex}">
    <p:ajax event="tabChange" listener="#{ataGerencialMB.onTabChange}"
            update="tab ,formListagemCapacitacao" />
    <p:tab title="#{tabView.sigla}">
        <p:dataTable    id="dtCapacitacao" 
                value="#{ataGerencialMB.lazyModelAtaGerencial}"
                var="gerencial"  
                lazy="true"
                paginator="true" 
                rows="#{Config.NUM_ROWS}"
                currentPageReportTemplate="#{Config.CURRENT_PAGE_REPORT_TEMPLATE}"
                paginatorTemplate="#{Config.PAGINATOR_TEMPLATE}"
                rowsPerPageTemplate="#{Config.ROWS_PER_PAGE_TEMPLATE}"
                sortBy="#{gerencial.idAta}" 
                sortOrder="ascending"
                reflow="true" 
                editable="true" 
                editMode="cell"
                rowKey="#{gerencial.idAta}">

        <p:ajax event="cellEdit"
                listener="#{ataGerencialMB.onCellEdit}" oncomplete="onCellEdit()"/>

        <p:column>
            <p:rowToggler/>
        </p:column>

        <p:column headerText="Tipo Assunto" >
            <p:cellEditor>
                <f:facet name="output">
                    <h:outputText value="#{gerencial.tipo}" 
                                  rendered="true" />
                </f:facet>

                <f:facet name="input">
                    <p:inputTextarea id="tipo" 
                       value="#{gerencial.tipo}" 
                       style="width:96%" />
                </f:facet>
            </p:cellEditor>
        </p:column>
      </p:dataTable>
    </p:tab>
</p:tabView>

Class that extends the LazyDataModel AtaGerencialLazyDataModel

public class AtaGerencialLazyDataModel extends LazyDataModel<AtaGerencialBean> {

AtaGerencialBusiness ataBusiness = new AtaGerencialBusiness();
Map<String, Object> customFilters = new HashMap<String, Object>();
private List<AtaGerencialBean> listaAtaGerencialBean = new ArrayList<AtaGerencialBean>();

public AtaGerencialLazyDataModel(){
    this.setRowCount(ataBusiness.getAtaGerencialTotalCount(null));
}

public AtaGerencialLazyDataModel(SetorBean setor){
    customFilters.put("setor", setor);
    this.setRowCount(ataBusiness.getAtaGerencialTotalCount(customFilters));
}

@Override
public List<AtaGerencialBean> load(int first, int pageSize, String sortField,
        SortOrder sortOrder, Map<String, Object> filters){
    List<AtaGerencialBean> list = ataBusiness.fetchLazyAtaGerencial(first, pageSize, sortField, sortOrder, customFilters);
    this.setRowCount(ataBusiness.getAtaGerencialTotalCount(customFilters));
    setListaAtaGerencialBean(list);
    setWrappedData(list);
    return list;
}

@Override
public AtaGerencialBean getRowData(String rowKey){
    try{
        long id = Long.parseLong(rowKey);
        for (AtaGerencialBean bean : listaAtaGerencialBean) {
            if (bean.getIdAta() == id){
                return bean;
            }

        }

    }catch(Exception e){
        System.out.println(e.getMessage());
    }
    return null;

}

@Override
public Object getRowKey(AtaGerencialBean p) {
    return p.getIdAta();
}

public List<AtaGerencialBean> getListaAtaGerencialBean() {
    return listaAtaGerencialBean;
}

public void setListaAtaGerencialBean(
        List<AtaGerencialBean> listaAtaGerencialBean) {
    this.listaAtaGerencialBean = listaAtaGerencialBean;
}

}

The onCellEdit method

 @ManagedBean
 @ViewScoped
 public class AtaGerencialMB extends MB<AtaGerencialBean, 
 AtaGerencialBusiness> {

     private LazyDataModel<AtaGerencialBean> lazyModelAtaGerencial;    

     @SuppressWarnings("unused")
     public void onCellEdit(CellEditEvent event) {
      try{
        DataTable controladorTabela = (DataTable) event.getComponent();
        //rowindex is fine, it brings the index of the edited row in the 
 datatable (from 0 onwards)
        Integer rowIndex = event.getRowIndex();
        String rowKey = event.getRowKey();

        //rowKey is always null
        System.out.println("rowKey value:" + rowKey);

        AtaGerencialBean entity = (AtaGerencialBean) controladorTabela.getRowData(event.getRowKey());
        this.setRegistroDefinido(entity);
        super.atualizar();
    }catch(NullPointerException ex){
        System.out.println(ex.getMessage());
    }

  }
}

EDIT

I was able to circumvent the problem by NOT using the rowKey to retrieve the data and modifying the onCellEdit method to get the data from the Datamodel inside the Datatable.

I am not sure whether it is a good/bad practice, or if that's how you're supposed to retrieve the row when using LazyLoading.

Also, following @Kukeltje suggestion, I am now using PRIMEFACES 6.2

Modified onCellEdit method

    @ManagedBean
    @ViewScoped
    public class AtaGerencialMB extends MB<AtaGerencialBean, AtaGerencialBusiness> {

   private LazyDataModel<AtaGerencialBean> lazyModelAtaGerencial;    
    @SuppressWarnings("unused")
        public void onCellEdit(CellEditEvent event) {
            try{
                DataTable controladorTabela = (DataTable) event.getComponent();
                DataModel dm = (DataModel) controladorTabela.getValue();
                AtaGerencialBean entity = (AtaGerencialBean) dm.getRowData();           
                this.setRegistroDefinido(entity);
                super.atualizar();
            }catch(NullPointerException ex){
                System.out.println(ex.getMessage());

            }

        }

    }

Solution

  • I was able to circumvent the problem by NOT using the rowKey to retrieve the data and modifying the onCellEdit method to get the data from the Datamodel inside the Datatable.

    I am not sure whether it is a good/bad practice, or if that's how you're supposed to retrieve the row when using LazyLoading.

    Also, following @Kukeltje suggestion, I am now using PRIMEFACES 6.2

    Modified onCellEdit method

    @SuppressWarnings("unused")
        public void onCellEdit(CellEditEvent event) {
            try{
                DataTable controladorTabela = (DataTable) event.getComponent();
                DataModel dm = (DataModel) controladorTabela.getValue();
                AtaGerencialBean entity = (AtaGerencialBean) dm.getRowData();           
                this.setRegistroDefinido(entity);
                super.atualizar();
            }catch(NullPointerException ex){
                System.out.println(ex.getMessage());
    
            }
    
        }