web-dev-qa-db-ja.com

Spring + Thymeleaf-リストのページネーションを実装する方法

Spring + Thymeleafを使用して簡単なアプリケーションを開発しています。ページの1つに、ページ分割する必要がある項目のリストがあります。

理想的には、currPageNo(現在のページの数)とnumOfPages(ページの総数)の変数のみをビューに送信し、残りの作業は、あります(これはプレゼンテーションの問題であり、ビジネスロジックとは関係ありません)。ただし、最もクリーンなソリューションで最初にコントローラーでいくつかの計算を行う必要がある場合は、それを小さな悪として受け入れます。

次の形式でページのリストを取得したいと思います。

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

私は次の解決策しか手に入れることができませんでした。それは機能しますが、あなたはそれが非常に面倒で本当に読むのが難しいことに同意するでしょう。

さらに、currPageNonumOfPagesに加えて、ビューにさらに2つの変数を送信する必要がありました。理想的な解決策は、私がそうすることを要求しないでしょう。

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

私のコードの現在のバージョンは次のとおりです。

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

以下のリストは、私が最も取り除きたい問題を要約したものです。それらの一部はプラットフォームに固有のものであると理解していますが、それでもリストは長く終了し、コードが乱雑になっているようです。

  • firstPageNolastPageNoの事前計算された値をコントローラーからビューに送信する必要があります。
  • 式で&lt;の代わりに<を使用する必要があります。
  • ブラウザーが現在のページのリンクを使用しないようにするには、相互に排他的な条件でアンカーとスパンの両方を使用する必要があります。

また、コードの品質を向上させる方法に関するその他の提案も歓迎します。


私はおそらくこの質問がコードレビューサイトに適していることを理解していますが、Thymeleafはまだ小さなユーザーベースのテクノロジーであると思われるため、はるかに多くのユーザーがいるStack Overflowでかなり合理的な回答を期待していますベース(私は信じています)。

ただし、そのような質問がここで本当に歓迎されない場合は、必要なアドバイスを得るように閉じるのではなく、適切なサイトに移動することを検討してください。

14

http://www.javacodegeeks.com/2013/03/implement-bootstrap-pagination-with-spring-data-and-thymeleaf.html で説明されているソリューションと同様

ただし、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>
19
user3590144

別のオプションは、ベン・サーリーのソリューションです。私たちはそれを実装し、スムーズに動作しています: http://bthurley.wordpress.com/2012/07/18/spring-mvc-with-restful-datatables/

検索用のフィルター引数のようないくつかの項目がありませんが、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;
    }
}
2
Nabil M

これはほぼ準備ができています。

<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>
0
Mike