JSF、RichFaces、分页 [英] JSF, RichFaces, pagination

查看:19
本文介绍了JSF、RichFaces、分页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这里有很多关于 JSF 分页的帖子,但没有一个让我满意.

I know there are quite a number of posts regarding JSF paginatin here, but none of them satisfed me.

为了将相当大的数据拆分成页面,我打算使用 RichFaces Data 滚动组件.

To split pretty big data into pages I was going to use RichFaces Data scroller component.

它似乎适合这种情况,但它看起来像是人工"分页.

It appeared to be suitable for that, but it looks like it does "artificial" pagination.

我不喜欢这里的是它加载所有数据然后只显示其中的一部分.至少它似乎是这样做的.如果我错了,请纠正我.

What i don't like here is that it loads all data and then merely displays part of it. At least it appears to do so. Correct me if i'm wrong.

Rich faces 有很好的演示,但由于某种原因,他们跳过了 bean 定义——只有 xhtml.我看到有人提到了 ExtendedDataModel,但我发现的唯一示例并没有给我留下深刻印象.为什么我应该有 5 个屏幕代码来显示数据的子集?

Rich faces have nice demos, but by some reason they skip bean definitions- only xhtml. I saw some mention of ExtendedDataModel, but the only example i found didn't impress me. Why am i suposed to have 5 screen code just do display subset of data?

老实说,像分页这样简单的问题在 JSF 中碰巧非常复杂,我真的不明白为什么.

Honestly such a simple question as pagination happened to be very complex in JSF and i don't really get why.

所以我的问题是:1. Richfaces 可以只加载一页数据吗2. 不将其存储到会话中(我的意思是实际数据未列出状态-当前页面等)

So my questions are: 1. is it possible in Richfaces to load only one page of data 2. without storing it to session (i mean actual data not list state- current page, etc)

我只对 Richfaces 库感兴趣,因为我已经在我的项目中使用了它,并且不知道要引入对其他东西的依赖

I'm interested only in richfaces lib as already use it in my project and don't what to introduce dependency on somethin else

提前谢谢

推荐答案

在 RichFaces 论坛上讨论后提出了以下解决方案(感谢 Brendan Healey):

After talking on RichFaces forum came up this the following solution (thanx to Brendan Healey):

RichLazyDataModel.java

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

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

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(部分)

cards.xhtml (partial)

...

<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>
...

这篇关于JSF、RichFaces、分页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆