Spring + Thymeleaf - 如何实现列表的分页

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18490820/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 06:11:17  来源:igfitidea点击:

Spring + Thymeleaf - how to implement pagination for a list

springpaginationthymeleaf

提问by Du?an Rychnovsky

I am developing a simple application using Spring + Thymeleaf. On one of the pages I have a list of items which needs to be paginated.

我正在使用 Spring + Thymeleaf 开发一个简单的应用程序。在其中一页上,我有一个需要分页的项目列表。

Ideally I would like to only send the currPageNo(the number of the current page) and numOfPages(the total number of pages) variables to the view and the rest of the work would be done in there (this is a presentation issue and has nothing to do with the business logic). If, however, the cleanest solution would require me to do some computation in the controller first, I would accept it as a small evil.

理想情况下,我只想将currPageNo(当前页面的数量)和numOfPages(页面总数)变量发送到视图,其余的工作将在那里完成(这是一个演示问题,无关紧要)与业务逻辑)。然而,如果最干净的解决方案需要我首先在控制器中进行一些计算,我会接受它作为一个小恶魔。

I would like to get the list of pages in the following form.

我想以以下形式获取页面列表。

<Prev | 1 | ... | 3 | 4 | 5 | 6 | 7 | ... | 15 | Next>

I was only able to come with the following solution. It works but I believe that you will agree that it is very messy and really hard to read.

我只能提供以下解决方案。它有效,但我相信您会同意它非常混乱且难以阅读。

Moreover, in addition to currPageNoand numOfPagesI had to send two more variables to the view. The ideal solution would not require me to do that.

此外,除了currPageNonumOfPages我不得不向视图发送另外两个变量。理想的解决方案不需要我这样做。

firstPageNo = Math.max(2, currPageNo - 2)
lastPageNo = Math.min(numOfPages - 1, currPageNo + 2)

The current version of my code follows.

我的代码的当前版本如下。

<ul>
    <li th:if="${currPageNo &gt; 1}">
        <a th:href="@{/items.html(pageNo = ${currPageNo - 1})}" href="">&lt; Prev</a>
    </li>
    <li th:class="${currPageNo == 1} ? 'selected'">
        <a th:href="@{/items.html(pageNo = 1)}" th:if="${currPageNo &gt; 1}" href="">1</a>
        <span th:if="${currPageNo == 1}">1</span>
    </li>
    <li th:if="${currPageNo &gt;= 5}">
        ...
    </li>
    <li th:each="pageNo : ${#numbers.sequence(firstPageNo, lastPageNo)}"  th:class="${currPageNo == pageNo} ? 'selected'">
        <a th:href="@{/items.html(pageNo = ${pageNo})}" th:if="${pageNo != currPageNo}" th:text="${pageNo}" href="">2</a>
        <span th:if="${pageNo == currPageNo}" th:text="${pageNo}">2</span>
    </li>
    <li th:if="${currPageNo &lt;= (numOfPages - 4)}">
        ...
    </li>
    <li th:class="${currPageNo == numOfPages} ? 'selected'">
        <a th:href="@{/items.html(pageNo = ${numOfPages})}" th:if="${currPageNo &lt; numOfPages}" th:text="${numOfPages}" href="">10</a>
        <span th:if="${currPageNo == numOfPages}" th:text="${numOfPages}">1</span>
    </li>
    <li th:if="${currPageNo &lt; numOfPages}">
        <a th:href="@{/items.html(pageNo = ${currPageNo + 1})}" href=""> Next &gt;</a>
    </li>
</ul>

The following list sumarizes the issues that I would like to get rid of the most. I understand that some of them are inherent to the platform but still, the list seems to be quit long and the code messy.

以下列表总结了我最想摆脱的问题。我知道其中一些是平台固有的,但列表似乎很长,代码也很混乱。

  • Having to send the precomputed values of firstPageNoand lastPageNoto the view from the controller.
  • Having to use &lt;instead of <in the expressions.
  • Having to use both an anchor and a span with mutually exclusive conditions in order for the browser not to use a link for the current page.
  • 无需发送的预先计算的值firstPageNo,并lastPageNo从控制器的看法。
  • 必须在表达式中使用&lt;而不是<
  • 必须同时使用具有互斥条件的锚点和跨度,以便浏览器不使用当前页面的链接。

I also welcome any other suggestions about how to improve the quality of the code.

我也欢迎关于如何提高代码质量的任何其他建议。



I understand that perhaps this question would be a better fit for the Code Review site, but, as Thymeleaf seems to be a technology with a tiny user base yet, I expect a reasonable answer rather here on Stack Overflow, which has a much greater user base (I believe).

我知道这个问题可能更适合 Code Review 网站,但是,由于 Thymeleaf 似乎是一种用户群很小的技术,我希望在 Stack Overflow 上有一个合理的答案,它有更多的用户基地(我相信)。

If, however, such a question is really not welcome here, please consider moving it to the right site instead of closing it so that I get the advice I need.

但是,如果这样的问题在这里真的不受欢迎,请考虑将其移至正确的站点而不是关闭它,以便我获得所需的建议。

回答by user3590144

Similar to solution described in http://www.javacodegeeks.com/2013/03/implement-bootstrap-pagination-with-spring-data-and-thymeleaf.html

类似于http://www.javacodegeeks.com/2013/03/implement-bootstrap-pagination-with-spring-data-and-thymeleaf.html 中描述的解决方案

but without using wrapper around Spring Pageable

但没有在 Spring Pageable 周围使用包装器

<div class="table-pagination">
    <ul class="pagination">
        <li th:class="${contactsPage.number eq 0} ? 'disabled' : ''">
            <a th:if="${not contactsPage.firstPage}" th:href="@{${'/contacts'}(page=${contactsPage.number-1},size=${contactsPage.size})}">Previous</a>
            <a th:if="${contactsPage.firstPage}" href="javascript:void(0);">Previous</a>
        </li>

        <li th:each="pageNo : ${#numbers.sequence(0, contactsPage.totalPages - 1)}" th:class="${contactsPage.number eq pageNo}? 'active' : ''">
            <a th:if="${contactsPage.number  eq pageNo}" href="javascript:void(0);">
                <span th:text="${pageNo + 1}"></span>
            </a>
            <a th:if="${not (contactsPage.number  eq pageNo)}" th:href="@{${'/contacts'}(page=${pageNo},size=${contactsPage.size})}">
                <span th:text="${pageNo + 1}"></span>
            </a>

        </li>
        <li th:class="${contactsPage.number + 1 ge contactsPage.totalPages} ? 'disabled' : ''">
            <a th:if="${not contactsPage.lastPage}" th:href="@{${'/contacts'}(page=${contactsPage.number+1},size=${contactsPage.size})}">Next</a>
            <a th:if="${contactsPage.lastPage}" href="javascript:void(0);">Next</a>
        </li>
    </ul>
</div>

回答by Nabil M

Another option would be Ben Thurley's solution. We have implemented it and it's working smoothly: http://bthurley.wordpress.com/2012/07/18/spring-mvc-with-restful-datatables/

另一种选择是 Ben Thurley 的解决方案。我们已经实施了它并且运行顺利:http: //bthurley.wordpress.com/2012/07/18/spring-mvc-with-restful-datatables/

It lacks couples of items, like the filter argument for the search, but you can easily add via the PagingCriteria object and make sure to add it on the TableParamArgumentResolver.

它缺少几个项目,例如用于搜索的过滤器参数,但您可以通过 PagingCriteria 对象轻松添加,并确保将其添加到 TableParamArgumentResolver 上。

public class TableParamArgumentResolver implements WebArgumentResolver {

    private static final String S_ECHO           = "sEcho";
    private static final String I_DISPLAY_START  = "iDisplayStart";
    private static final String I_DISPLAY_LENGTH = "iDisplayLength";
    private static final String I_SORTING_COLS   = "iSortingCols";

    private static final String I_SORT_COLS      = "iSortCol_";
    private static final String S_SORT_DIR       = "sSortDir_";
    private static final String S_DATA_PROP      = "mDataProp_";
    private static final String I_DATA_SEARCH    = "sSearch";

    public Object resolveArgument(MethodParameter param, NativeWebRequest request)
            throws Exception {
        TableParam tableParamAnnotation = param.getParameterAnnotation(TableParam.class);

        if (tableParamAnnotation != null) {
            HttpServletRequest httpRequest = (HttpServletRequest) request.getNativeRequest();

            String sEcho = httpRequest.getParameter(S_ECHO);
            String sDisplayStart = httpRequest.getParameter(I_DISPLAY_START);
            String sDisplayLength = httpRequest.getParameter(I_DISPLAY_LENGTH);
            String sSortingCols = httpRequest.getParameter(I_SORTING_COLS);
            String sSearch = httpRequest.getParameter(I_DATA_SEARCH);

            Integer iEcho = Integer.parseInt(sEcho);
            Integer iDisplayStart = Integer.parseInt(sDisplayStart);
            Integer iDisplayLength = Integer.parseInt(sDisplayLength);
            Integer iSortingCols = Integer.parseInt(sSortingCols);

            List<SortField> sortFields = new ArrayList<SortField>();
            for (int colCount = 0; colCount < iSortingCols; colCount++) {
                String sSortCol = httpRequest.getParameter(I_SORT_COLS + colCount);
                String sSortDir = httpRequest.getParameter(S_SORT_DIR + colCount);
                String sColName = httpRequest.getParameter(S_DATA_PROP + sSortCol);
                sortFields.add(new SortField(sColName, sSortDir));
            }

            PagingCriteria pc = new PagingCriteria(iDisplayStart, iDisplayLength, iEcho, sortFields, sSearch);

            return pc;
        }

        return WebArgumentResolver.UNRESOLVED;
    }
}

回答by Mike

I have this almost ready, hope it helps....

我已经准备好了,希望它有帮助......

<div class="tag-box tag-box-v7 text-justify">
    <div class="text-center">
        <ul class="pagination" th:with="elementsperpage=2, blocksize=10, pages=${page2th.Number}/${elementsperpage}, wholepages=${format.format(pages)},
whole=(${page2th.Number}/${blocksize})+1, wholex=${format.format(whole)}, startnlockpage=${wholepages}*${blocksize+1}, endblockpage=${wholepages}*${blocksize+1}, 
startpage=${wholex-1}*${blocksize}, endpage=(${wholex}*${blocksize})+1">

            <li>
                <a th:if="${startpage gt 0}" th:href="@{${'/viewannouncements?p='}+${startpage}}">&lt;&lt;</a>
                <a th:if="${startpage eq 0}" href="javascript:void(0);">&lt;&lt;</a>
            </li>

            <li th:each="pageNo : ${#numbers.sequence(endpage-11, (endpage lt page2th.TotalPages)? endpage-2 : page2th.TotalPages-1)}" 
            th:class="${page2th.Number eq pageNo}? 'active' : ''">
                    <a th:if="${page2th.Number eq pageNo}" href="javascript:void(0);">
                        <span th:text="${pageNo + 1}"></span>
                    </a>
                    <a th:if="${not (page2th.Number  eq pageNo)}" th:href="@{${'/viewannouncements?p='}+${pageNo+1}}">
                        <span th:text="${pageNo + 1}"></span>
                    </a>
            </li>

            <li>
                <a th:if="${(endpage*elementsperpage) le (page2th.TotalElements)}" th:href="@{${'/viewannouncements?p='}+${endpage}}">&gt;&gt;</a>
                <a th:if="${(endpage*elementsperpage) le (page2th.TotalElements)}" href="javascript:void(0);"></a>
            </li>



        </ul>
    </div>
</div>