2013-08-28 108 views
10

Tôi đang phát triển một ứng dụng đơn giản bằng Spring + Thymeleaf. Trên một trong các trang tôi có một danh sách các mục cần được phân trang.Spring + Thymeleaf - cách triển khai phân trang cho một danh sách

Lý tưởng nhất là tôi chỉ muốn gửi các biến số currPageNo (số trang hiện tại) và numOfPages (tổng số trang) vào chế độ xem và phần còn lại của công việc sẽ được thực hiện trong đó (đây là bản trình bày vấn đề và không liên quan gì đến logic nghiệp vụ). Tuy nhiên, nếu giải pháp sạch nhất sẽ yêu cầu tôi thực hiện một số tính toán trong bộ điều khiển đầu tiên, tôi sẽ chấp nhận nó như một cái ác nhỏ.

Tôi muốn nhận danh sách các trang trong biểu mẫu sau.

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

Tôi chỉ có thể đi kèm với giải pháp sau đây. Nó hoạt động nhưng tôi tin rằng bạn sẽ đồng ý rằng nó rất lộn xộn và thực sự khó đọc.

Ngoài ra, ngoài currPageNonumOfPages Tôi phải gửi thêm hai biến cho chế độ xem. Giải pháp lý tưởng sẽ không yêu cầu tôi làm điều đó.

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

Phiên bản hiện tại của mã của tôi theo sau.

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

Danh sách sau đây tổng hợp các vấn đề mà tôi muốn loại bỏ nhất. Tôi hiểu rằng một số người trong số họ là cố hữu với nền tảng nhưng vẫn còn, danh sách có vẻ là bỏ thuốc lá dài và mã lộn xộn.

  • Phải gửi giá trị precomputed firstPageNolastPageNo cho chế độ xem từ bộ điều khiển.
  • Phải sử dụng &lt; thay vì < trong biểu thức.
  • Phải sử dụng cả neo và nhịp với các điều kiện lẫn nhau để trình duyệt không sử dụng liên kết cho trang hiện tại.

Tôi cũng hoan nghênh mọi đề xuất khác về cách cải thiện chất lượng của mã.


Tôi hiểu rằng có lẽ câu hỏi này sẽ là phù hợp hơn cho các trang web Mã Rà soát, nhưng, như Thymeleaf có vẻ là một công nghệ với một cơ sở người dùng nhỏ nào, tôi mong đợi một câu trả lời hợp lý chứ không phải ở đây trên Stack Overflow , có cơ sở người dùng lớn hơn nhiều (tôi tin).

Nếu, tuy nhiên, câu hỏi như vậy thực sự không được chào đón ở đây, vui lòng cân nhắc chuyển nó sang đúng trang thay vì đóng để tôi nhận được lời khuyên mà tôi cần.

Trả lời

2

Một tùy chọn khác sẽ là giải pháp của Ben Thurley. Chúng tôi đã triển khai nó và hoạt động trơn tru: http://bthurley.wordpress.com/2012/07/18/spring-mvc-with-restful-datatables/

Nó thiếu các mục, như đối số lọc cho tìm kiếm, nhưng bạn có thể dễ dàng thêm thông qua đối tượng PagingCriteria và đảm bảo thêm nó vào 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; 
    } 
} 
18

Tương tự như giải pháp được mô tả trong http://www.javacodegeeks.com/2013/03/implement-bootstrap-pagination-with-spring-data-and-thymeleaf.html

nhưng mà không sử dụng bao bọc xung quanh mùa xuân 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> 
+2

Vui lòng bao gồm một số văn bản như giải thích bằng mã. –

+2

Không chỉ đổ mã ... thêm một số thịt vào nó là tốt. – Werner

+1

Lưu ý rằng bây giờ bạn phải thay thế 'firstPage' và' lastPage' bằng 'first' và' last'. – membersound

1

Tôi có điều này gần như đã sẵn sàng, hy vọng nó sẽ giúp ....

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