ActionListener commandLink not working with lazy data. Scroller

In a project, I need a lazy load object from the database, and for each item I will put a link to redirect to a specific page.

Lazy loading works. and when clicking the link for the first item it is ok, the problem after scrolling, the next item is not calling the listOi.editer ().

<p:dataScroller value="#{listOi.lazyOi}" var="oi" id="OisChoser" widgetVar="scroller" 
  chunkSize="5" mode="inline" scrollHeight="531" lazy="true" style="width: 597px;" rows="5" >
  <h:panelGroup id="info_OI" class="info_OI" align="center" >
   ...
   <h:commandLink actionListener="#{listOi.editer()}" immediate="true" >
     <f:param name="selectedoiId" value="#{oi.id}" />
     <span class="crayon" style='cursor: pointer;'></span>
   </h:commandLink>
   ...
  </h:panelGroup 
</p:dataScroller>

      

+3


source to share


1 answer


The problem is that PrimeFaces LazyDataModel

does not save the complete model of the data displayed in the view. It keeps track of newly loaded items and discards old items. This makes it impossible to access these elements from JSF.

But since you subclass this class anyway (it's abstract), it's pretty easy to change this behavior. Basically what you want to do is keep track of all the data you've uploaded and return that data when requested. At a minimum, you need to override setRowIndex()

, getRowData()

, isRowAvailable()

and load()

. Below is an example that works for me.

public class MyLazyModel extends LazyDataModel<SomeType> implements Serializable {

    private final List<SomeType> data;
    private int rowIndex;

    public MyLazyModel() {
        super();
        data = new ArrayList<>();
    }

    @Override
    public List<SomeType> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
        List<SomeType> retData;
        if (first >= data.size()) {
            retData = ... //Get the data from datasource
            data.addAll(retData);
            return retData;
        } else {
            return data.subList(first, Math.min(first + pageSize, data.size()));
        }
    }

    @Override
    public void setRowIndex(int index) {
        if (index >= data.size()) {
            index = -1;
        }
        this.rowIndex = index;
    }

    @Override
    public SomeType getRowData() {
        return data.get(rowIndex);
    }

    @Override
    public boolean isRowAvailable() {
        if (data == null) {
            return false;
        }
        return rowIndex >= 0 && rowIndex < data.size();
    }

}

      



Because you can never be sure that setWrappedData()

(which is called after load()

with the return data from this method) is called only once, you need to guard against adding duplicates to your data model. Here I only do this by loading data that has never been loaded before and storing that data in a method load()

, completely ignoring it setWrappedData()

. This is pretty ugly and will lead to synchronization problems if your model is never invalidated, but it works. In any case, you can work around this by always loading data and replacing the old content with the new one, but that is not the core of the problem.

Also, since you are now tracking the data in the method itself, you need to override all the methods in LazyDataModel

that rely on the LazyDataModel.data

correct ones (or at least the subset of them that you are using).

Final note: you should of course make sure that your model is returned to the JSF page, always the same as discussed here .

+2


source







All Articles