JSF2分页/重复器的页面导航器

13

你是否有那种每次编写代码都立即运行并且提前完成计划的感觉 :-P 就像是“哦,现在我有时间把它完美化”。这就是我目前的状态^^

因此,我使用JSF(ui:repeat)实现了一个重复器,并考虑对所有实体进行分页。也许有一种简单的方法来实现这个功能吗?我需要考虑哪些要点?

如果有人能给我一些帮助就好了。我的谷歌技巧到目前为止还没有帮助我 :-P

干杯...


你的应用程序中使用RichFaces吗? - Maxim Manco
我不会。但如果这有助于我,我可以学习。 - Sven
2个回答

20

这里有一个简单的示例,可以帮助你了解如何实现这个功能。

RepeatPaginator:

public class RepeatPaginator {

    private static final int DEFAULT_RECORDS_NUMBER = 2;
    private static final int DEFAULT_PAGE_INDEX = 1;

    private int records;
    private int recordsTotal;
    private int pageIndex;
    private int pages;
    private List<?> origModel;
    private List<?> model;

    public RepeatPaginator(List<?> model) {
        this.origModel = model;
        this.records = DEFAULT_RECORDS_NUMBER;
        this.pageIndex = DEFAULT_PAGE_INDEX;        
        this.recordsTotal = model.size();

        if (records > 0) {
            pages = records <= 0 ? 1 : recordsTotal / records;

            if (recordsTotal % records > 0) {
                pages++;
            }

            if (pages == 0) {
                pages = 1;
            }
        } else {
            records = 1;
            pages = 1;
        }

        updateModel();
    }

    public void updateModel() {
        int fromIndex = getFirst();
        int toIndex = getFirst() + records;

        if(toIndex > this.recordsTotal) {
            toIndex = this.recordsTotal;
        }

        this.model = origModel.subList(fromIndex, toIndex);
    }

    public void next() {
        if(this.pageIndex < pages) {
            this.pageIndex++;
        }

        updateModel();
    }

    public void prev() {
        if(this.pageIndex > 1) {
            this.pageIndex--;
        }

        updateModel();
    }   

    public int getRecords() {
        return records;
    }

    public int getRecordsTotal() {
        return recordsTotal;
    }

    public int getPageIndex() {
        return pageIndex;
    }

    public int getPages() {
        return pages;
    }

    public int getFirst() {
        return (pageIndex * records) - records;
    }

    public List<?> getModel() {
        return model;
    }

    public void setPageIndex(int pageIndex) {
        this.pageIndex = pageIndex;
    }

}

Bean:

public class TestBean {

    private List<String> list;
    private RepeatPaginator paginator;

    @PostConstruct
    public void init() {
        this.list = new ArrayList<String>();
        this.list.add("Item 1");
        this.list.add("Item 2");
        this.list.add("Item 3");
        this.list.add("Item 4");
        this.list.add("Item 5");
        this.list.add("Item 6");
        this.list.add("Item 7");
        this.list.add("Item 8");
        this.list.add("Item 9");
        this.list.add("Item 10");
        this.list.add("Item 11");
        paginator = new RepeatPaginator(this.list);
    }

    public RepeatPaginator getPaginator() {
        return paginator;
    }

}

XHTML:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    template="/WEB-INF/template/default.xhtml">

<ui:define name="content">
    <h:form>
        <ui:repeat value="#{testBean.paginator.model}" var="listItem">
            <div>
                <h:outputText value="#{listItem}"/>
            </div>
        </ui:repeat>
        <h:commandButton value="&lt; prev" action="#{testBean.paginator.prev}"/>
        <h:outputText value="#{testBean.paginator.pageIndex} / #{testBean.paginator.pages}"/>
        <h:commandButton value="next &gt;" action="#{testBean.paginator.next}"/>
        <h:inputHidden value="#{testBean.paginator.pageIndex}"/>
    </h:form>
</ui:define>
</ui:composition>

@mmanco,您能否在UIRepeater中动态创建commandLinks? - John John Pichler

9
分页其实很简单。你只需要传递一个或两个参数:firstrow和可选的rowcount(也可以保存在服务器端)。当用户点击“下一页”时,你只需将firstrow的值增加rowcount的值。当用户点击“上一页”时,你只需将firstrow的值减去rowcount的值。你只需要检查它是否超出0totalrows的边界,并相应地进行更改。

然后,根据所需的firstrowrowcount,您知道要显示哪些数据。如果所有数据已经在Java内存中的某个List中,则只需使用{{link1:List#subList()}}从中获取子列表以进行显示。但是,将整个数据库表复制到Java的内存中并不高效。当它只有100行时可能没有问题,但是当它远远超过这个数量和/或您为每个单独的用户复制它时,应用程序很快就会耗尽内存。

在这种情况下,您更希望在数据库层面进行分页。例如,在MySQL中,您可以使用LIMIT子句从数据库获取结果的子集。甚至JPA / Hibernate提供了使用QueryCriteriasetFirstResult()setMaxResults()方法的方式。您可以在thisthis答案中找到示例。
您可以在this article中找到一个基本的JSF 1.2目标启动示例,用于类似Google的分页(和排序)。它使用Tomahawk组件,但在JSF 2.0中,您可以通过使bean @ViewScoped(替换t:saveState)并使用ui:repeat(替换t:dataList)来省略它们。

最后但并非最不重要的,有许多组件库可以在单个组件中完成所有工作。例如 RichFaces <rich:datascroller>PrimeFaces <p:dataTable paginator="true">(也可以通过 ajaxical 完成)。


嗯,我真的很惊讶,你没有包含一个典型的“BalusC-kickoff”示例。:) 不过,无论如何,我仍然喜欢这种数据库方法。 - alexander
@BalusC:你好,看起来primefaces在查看此链接[http://blog.primefaces.org/?p=1808]后引入了ui:repeat分页,但是文章内部的链接无效,请问您能否澄清一下这一点?是否有适用于ui:repeat分页的primefaces解决方案? - Jad Chahine
@Jad:这是 <p:dataList> - BalusC
非常感谢!我找到了这个网址:http://www.primefaces.org/showcase/ui/data/dataList.xhtml - Jad Chahine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接