Перезагрузка ‹p:dataScroller› при обновлении формы

Случайная мысль: я ненавижу это поведение «одинокого волка», которое они закодировали в dataScroller....


Я пытаюсь реализовать фильтр на основе выбора пользователя в <p:selectOneMenu>, который будет перезагружать содержимое, показанное в <p:dataScroller>, из ManagedBean на основе выбора.

МБ (EnglishNumberToWords) (random строки)

import java.util.*;
import se.answers.EnglishNumberToWords;
import java.security.SecureRandom;

@ManagedBean
@ViewScoped
public class bean {
private List<String> itens;
private Integer choice = 1; //initialize;
private LazyDataModel<String> model;
// getter setter

@PostConstruct
public void postConstruct() {
    int count = loadStringsFromElsewhere();
    model = new LazyModelImplmentation(this);
    model.setRowCount(count);
}

public Map<String, Integer> mapChoices() {
    Map<String, Integer> map = new LinkedHashMap<String, Integer>();
    for(int ii=0;ii<5;ii++) {
        map.put(ii, convertLessThanOneThousand(ii));
    }
}

public List<String> getChunk(int first, int pageSize) {
    SecureRandom random = new SecureRandom();
    int listSize = itens.size();
    int added = 0;
    int end = int+pageSize;
    while(end > itens.size(){
        added++; //the real code here is different, I will just randomize.
        int criteria = (random.nextInt(5) + 1);
        if(criteria == choice) { // filters out Strings.
            String ss = criteria + BigInteger(130, random).toString(32)
            itens.add(ss);
        }
    }
    return itens.subList(Math.min(first, itens.size()), Math.min(end, itens.size()));
    }

/**
 *  Get the dataScroller itens from elsewhere, NOT a database.<p>
 *  here we will use only randons.
 */
private int loadStringsFromElsewhere() {
    SecureRandom random = new SecureRandom();
    if(itens == null) {
       itens = new ArrayList<String>();
    }
    for(int ii=0;ii<  (random.nextInt(50) + 100); ii++) {
        int criteria = (random.nextInt(5) + 1);
        String ss = criteria + BigInteger(130, random).toString(32);
        itens.add(ss);
    }
}
}

LazyModelImpl

import java.util.List;
import java.util.Map;

import org.primefaces.model.LazyDataModel;
import org.primefaces.model.SortOrder;

public class LazyModelImplmentation extends LazyDataModel<String> {
    private static final long serialVersionUID = 1L;
    private Bean bean;

public LazyModelImplmentation(Bean bean) {
    this.bean = bean;
}

@Override
    public List<String> load(int first, int pageSize, String sortField,
            SortOrder sortOrder, Map<String, Object> filters) {
        return bean.getChunk(first, pageSize);
    }   
}

JSF

<h:form prependId="false">
   <p:selectOneMenu value="#{bean.choice}">
        <f:selectItems value="#{bean.mapChoices()}" />
        <p:ajax process="@form" update="@form" />
    </p:selectOneMenu> 
    <p:dataScroller id="da_scroller" var="item" 
        value="#{bean.model}" rowIndexVar="index" chunkSize="10" lazy="true">

    <!-- SHOW THE DATA IN THE item -->
        <h:outputText value="#{index}: #{item.toString()}" />
        <hr />

    </p:dataScroller>
</h:form>

Но dataScroller просто игнорирует обновление формы и продолжает показывать одни и те же данные. Обновляются только новые данные, загруженные через ленивую модель, смешиваясь со старыми данными.

Как я могу очистить dataScroller при обновлении формы, чтобы он отображал только новые данные (бонусные баллы, если он возвращается к первому фрагменту).

Использование Primefaces 5.0 на Tomcat 7 и jsf2.2 (но jsf указан в тегах).


person Mindwin    schedule 03.07.2015    source источник
comment
Обновление формы, в которой находится прокрутка данных, похоже, не является триггером «сброса». Проверьте источник javascript прокрутки данных, чтобы увидеть, содержит ли он какие-либо скрытые функции для достижения этой цели. В противном случае посмотрите, содержит ли источник java что-то, что вы можете использовать через привязку.   -  person Kukeltje    schedule 07.07.2015
comment
Спасибо. Если вы превратите это в своего рода метод reset(), вы можете отправить его как патч / запрос на извлечение в github PF.   -  person Kukeltje    schedule 07.07.2015
comment
@Kukeltje Отправка патча может быть для меня слишком сложной задачей. И исторически сложилось так, что у парней из PF есть своя собственная дорожная карта. Однако я постараюсь задокументировать свое решение как можно лучше.   -  person Mindwin    schedule 07.07.2015
comment
Я знаю… но в последнее время все немного изменилось с переходом на github. По крайней мере, для исправления ошибок.   -  person Kukeltje    schedule 07.07.2015
comment
Ответ @Kukeltje опубликован. Я удалю некоторые устаревшие комментарии здесь, предлагаю вам сделать то же самое.   -  person Mindwin    schedule 07.07.2015
comment
Готово, но имейте в виду. Jsf 2.2 — это не реализация и версия, это API и версия. Mojarra/MyFaces 2.2.x - это то, что нужно опубликовать   -  person Kukeltje    schedule 07.07.2015


Ответы (2)


Повозившись с источником <p:dataScroller>, я не нашел решения. Нет задокументированного способа изменить то, что уже было добавлено, и компонент просто добавляет больше материала.

Поэтому мне пришлось взломать собственное решение:

  1. Соврать <p:dataScroller>:

    • The component does not work properly if you do not setRowCount() on the lazyModel. It only fetches two chunks and then stop.
    • Изменение rowCount на лету также не дает ожидаемого эффекта. Компонент ведет собственный внутренний счет. [3]
    • Также, начиная с Primefaces 5.0, установка для rowCount значения Integer.MAX_VALUE приводит к тому, что dataScroller останавливается (на стороне клиента) при выборке второго фрагмента. Я подозреваю, что это какой-то художник Шлемиэль [1] [< href="https://en.wikipedia.org/wiki/Joel_Spolsky#Schlemiel_the_Painter.27s_algorithm" rel="nofollow noreferrer">2].
    • Итак, при инициализации LazyDataModel установите достаточно большое значение rowCount (но не слишком большое). Я поставил 100000.
  2. Обман: я контролирую, что поступает в dataScroller, потому что я строю фрагмент на @ManagedBean, поэтому, если я хочу сбросить список и начать обслуживание с самого начала, я могу это сделать. Я оставлю точную реализацию метода getChunk() (см. листинг к вопросу выше) читателю, но просто ведите собственный подсчет вместо того, чтобы полагаться на параметры LazyDataModel<T>.load().

  3. Украсть: очистите уже загруженные записи в вызове AJAX <p:selectOneMenu> (привяжите к onstart, потому что вы не можете быть уверены, что у вас есть окно для этого до того, как dataScroller обновит себя:
<p:selectOneMenu value="#{bean.choice}">
    <f:selectItems value="#{bean.mapChoices()}" />
    <p:ajax process="@form" update="@form"  onstart="cleanScroller()" />
</p:selectOneMenu>
function cleanScroller() {
    $('li.ui-datascroller-item').remove();
}
person Mindwin    schedule 07.07.2015

Есть простой способ:
Просто поместите прокрутку данных внутрь панели, а затем:

  • измените отображаемый атрибут на false в прокрутке данных
  • обновить панель
  • перезагрузить список прокрутки данных новыми данными
  • снова измените отображаемый атрибут на true в прокрутке данных
  • обновить панель

= )

person Vitor Mendes Costa    schedule 06.11.2016