2014-09-08 4 views
3

В проекте мне нужен ленивый объект загрузки из базы данных, и для каждого элемента я поставлю ссылку на перенаправление на определенную страницу.actionListener commandLink не работает с ленивыми даннымиScroller

Работает от lazy. и при щелчке по ссылке для первого элемента это нормально, проблема возникает после прокрутки, следующий элемент не вызывает listner 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> 
+0

Я столкнулся с той же проблемой и ответил на [мой собственный вопрос] (https://stackoverflow.com/questions/25409316/commandlink-not-working-on-a-lazy-loaded-primefaces-datascroller/26222914# 26222914) –

ответ

2

Проблема заключается в том, что PrimeFaces 'LazyDataModel не сохраняет полную модель данных, отображаемых в представлении. Он отслеживает только что загруженные элементы и отбрасывает старые элементы. Это делает невозможным доступность этих элементов из JSF.

Но поскольку вы все равно подклассифицируете этот класс (он абстрактный), довольно легко изменить это поведение. В основном, что вы хотите сделать, это отслеживать все загруженные вами данные и возвращать эти данные по запросу. Как минимум, вам необходимо переопределить setRowIndex(), getRowData(), isRowAvailable() и load(). Ниже приведен пример, который работает для меня.

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

} 

Потому что вы никогда не можете быть уверены, что setWrappedData() (который вызывается после load() с данными возврата из этого метода) вызывается только один раз, вы должны принять меры против добавления двойников в вашей модели данных. Здесь я делаю это только путем загрузки данных, которые никогда не были загружены до и хранения этих данных в методе load(), полностью игнорируя setWrappedData(). Это довольно уродливо и приведет к проблемам синхронизации, если ваша модель никогда не признана недействительной, но она работает. В любом случае, вы можете обойти это, всегда загружая данные и заменяя старый контент на новый, но это не является основной причиной проблемы.

Кроме того, поскольку вы теперь отслеживаете данные в самом методе, вам необходимо переопределить все методы в LazyDataModel, которые полагаются на LazyDataModel.data правильной (или, по крайней мере, той подмножестве, которую вы используете).

Заключительное примечание: вы, конечно, должны убедиться, что ваша модель вернулась на страницу JSF, всегда такая же, как обсуждалось here.

Смежные вопросы