7

ここにはJSFのページナインに関する投稿がかなりあることは知っていますが、どれも私を満足させるものではありませんでした.

かなり大きなデータをページに分割するために、RichFaces Data スクローラー コンポーネントを使用するつもりでした。

それに適しているように見えましたが、「人工的な」ページネーションを行っているようです。

ここで気に入らないのは、すべてのデータをロードしてから、その一部を表示するだけだということです。少なくともそうしているようです。私が間違っている場合は修正してください。

リッチフェイスには素晴らしいデモがありますが、何らかの理由で Bean 定義をスキップし、xhtml のみです。ExtendedDataModel についての言及を見ましたが、私が見つけた唯一の例は私を感動させませんでした。データのサブセットを表示するだけの 5 つのスクリーン コードを使用する必要があるのはなぜですか?

正直なところ、ページネーションのような単純な質問が、たまたま JSF では非常に複雑で、その理由がよくわかりません。

したがって、私の質問は次のとおりです。1.Richfacesで1ページのデータのみをロードすることは可能ですか?2.セッションに保存せずに(つまり、実際のデータではなく、状態の現在のページなどをリストします)

私は自分のプロジェクトで既に使用しているため、richfaces libにのみ興味があり、他の何かへの依存関係を導入する必要はありません

事前に感謝

4

1 に答える 1

4

RichFaces フォーラムで話し合った後、次の解決策が思いつきました (Brendan Healey に感謝します)。

RichLazyDataModel.java

/**
 * Extended data model
 * @author Brendan Healey
 */
public abstract class RichLazyDataModel<T> extends ExtendedDataModel<T> {

private SequenceRange cachedRange;
private Integer cachedRowCount;
private List<T> cachedList;
private Object rowKey;

public abstract List<T> getDataList(int firstRow, int numRows);
public abstract Object getKey(T t);
public abstract int getTotalCount();

@Override
public void walk(FacesContext ctx, DataVisitor dv, Range range, Object argument) {

    SequenceRange sr = (SequenceRange) range;

    if (cachedList == null || !equalRanges(cachedRange, sr)) {
        cachedList = getDataList(sr.getFirstRow(), sr.getRows());
        cachedRange = sr;
    }

    for (T t : cachedList) {
        if (getKey(t) == null) {
            /*
            * the 2nd param is used to build the client id of the table
            * row, i.e. mytable:234:inputname, so don't let it be null.
            */
            throw new IllegalStateException("found null key");
        }
        dv.process(ctx, getKey(t), argument);
    }

}


/*
* The rowKey is the id from getKey, presumably obtained from
* dv.process(...).
*/
@Override
public void setRowKey(Object rowKey) {
    this.rowKey = rowKey;
}

@Override
public Object getRowKey() {
    return rowKey;
}

@Override
public boolean isRowAvailable() {
    return (getRowData() != null);
}

@Override
public int getRowCount() {
    if (cachedRowCount == null) {
        cachedRowCount = getTotalCount();
    }
    return cachedRowCount;
}

@Override
public T getRowData() {
    for (T t : cachedList) {
        if (getKey(t).equals(this.getRowKey())) {
            return t;
        }
    }
    return null;
}

protected static boolean equalRanges(SequenceRange range1, SequenceRange range2) {
    if (range1 == null || range2 == null) {
        return range1 == null && range2 == null;
    } else {
        return range1.getFirstRow() == range2.getFirstRow() && range1.getRows() == range2.getRows();
    }
}



/*
* get/setRowIndex are used when doing multiple select in an
* extendedDataTable, apparently. Not tested. Actually, the get method is
* used when using iterationStatusVar="it" & #{it.index}.
*/
@Override
public int getRowIndex() {
    if (cachedList != null) {
        ListIterator<T> it = cachedList.listIterator();
        while (it.hasNext()) {
            T t = it.next();
            if (getKey(t).equals(this.getRowKey())) {
                return it.previousIndex() + cachedRange.getFirstRow();
            }
        }
    }
    return -1;
}

@Override
public void setRowIndex(int rowIndex) {
    int upperBound = cachedRange.getFirstRow() + cachedRange.getRows();
    if (rowIndex >= cachedRange.getFirstRow() && rowIndex < upperBound) {
        int index = rowIndex % cachedRange.getRows();
        T t = cachedList.get(index);
        setRowKey(getKey(t));
    }
}

@Override
public Object getWrappedData() {
    throw new UnsupportedOperationException("Not supported yet.");
}

@Override
public void setWrappedData(Object data) {
    throw new UnsupportedOperationException("Not supported yet.");

}

public List<T> getCachedList() {
    return cachedList;
}

}

ListState.java

/**
 * Holds list state
 */
public class ListState implements Serializable {

private int page;

private Map<String, Serializable> searchCriteria = new HashMap<String, Serializable>();

public int getPage() {
    return page;
}

public void setPage(int page) {
    this.page = page;
}

public Map<String,Serializable> getSearchCriteria() {
    return searchCriteria;
}

}

CardsBean.java

@ManagedBean(name="cardsBean")
public class CardsBean {

@ManagedProperty("#{cardService}")
private CardService cardService;

private ListState state;

private RichLazyDataModel<Card> cardsModel = new RichLazyDataModel<Card>() {
    @Override
    public List<Card> getDataList(int firstRow, int numRows) {
        MyUserDetails user = SecurityUtils.getCurrentUser();
        return cardService.findUserCards(user.getUser(), firstRow, numRows, state.getSearchCriteria());
    }

    @Override
    public Object getKey(Card card) {
        return card.getId();
    }

    @Override
    public int getTotalCount() {
        MyUserDetails user = SecurityUtils.getCurrentUser();
        return cardService.countUserCards(user.getUser(), state.getSearchCriteria());
    }
};


public RichLazyDataModel<Card> getCards() {
    return cardsModel;
}

public String getSearchString() {
    return (String)state.getSearchCriteria().get("searchString");
}

public int getCurrentPage() {
    return state.getPage();
}

public void setCurrentPage(int page) {
    state.setPage(page);
}

public void setSearchString(String searchString) {
    state.getSearchCriteria().put("searchString", searchString);
}

public void setCardService(CardService cardService) {
    this.cardService = cardService;
}

public boolean isPinned() {
    return Boolean.TRUE.equals(state.getSearchCriteria().get("pinned"));
}

public void setPinned(boolean pinned) {
    state.getSearchCriteria().put("pinned", pinned);
}

public void togglePinned() {
    setPinned(!isPinned());
}

@PostConstruct
public void init() {
    state = getFromSession("cardsList", null);
    if (state == null) {
        state = new ListState();
        storeInSession("cardsList", state);
    }
}

public <T extends Serializable> T getFromSession(String name, T defaultValue) {
    T ret = (T) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get(name);
    if (ret == null) {
        ret = defaultValue;
    }
    return ret;
}

public void storeInSession(String name, Serializable obj) {
    FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(name, obj);
}
}

cards.xhtml (部分)

...

<h:form>

  <rich:dataGrid value="#{cardsBean.cards}" var="card" columns="2" elements="20" first="#{cardsBean.currentPage}" style="margin:0 auto;width:70em" id="cardsTable">
      <f:facet name="header">
          <h:inputText value="#{cardsBean.searchString}">
              <a4j:ajax event="keyup" render="cardsTable@body, cardsTable@footer">
                <a4j:attachQueue requestDelay="700" ignoreDupResponses="true" />
              </a4j:ajax>

          </h:inputText>
      </f:facet>

      <rich:panel id="cd">
          <ui:include src="WEB-INF/parts/card.xhtml">
              <ui:param name="card" value="#{card}"/>
          </ui:include>


      </rich:panel>

      <f:facet name="footer">
          <rich:dataScroller page="#{cardsBean.currentPage}"   />
      </f:facet>

  </rich:dataGrid>

  </h:form>
...
于 2012-08-18T11:21:43.893 に答える