Jin's Dev Story

[스프링 부트 쇼핑몰 프로젝트 with JPA] 8-2. [상품 관리] 상품 목록 페이지 본문

Web & Android/스프링 부트 쇼핑몰 프로젝트 with JPA

[스프링 부트 쇼핑몰 프로젝트 with JPA] 8-2. [상품 관리] 상품 목록 페이지

woojin._. 2023. 10. 16. 18:22
이 내용은 스프링 부트 쇼핑몰 프로젝트 with JPA 책을 학습한 내용입니다.

1. 상품 목록 페이지 결과 화면

  • 상품 목록 테이블 부분, 하단 페이지 부분, 검색 조건 부분 존재

2. 상품 목록 페이지 View

  • "검색" 버튼을 클릭하면 조회할 페이지 번호를 다시 "0"으로 설정해서 조회해야함
  • 페이지 번호를 전달 받아 form에 설정된 검색 조건 값들을 초기화하여 QueryString으로 보내는 page() 함수
<!-- 사용자 스트립트 추가 -->
<th:block layout:fragment="script">
      <script th:inline="javascript">

            $(document).ready(function(){
								// 검색 버튼이 눌리면
                  $("#searchBtn").on("click",function(e) {
												// form 태그의 전송을 막음 (페이지 번호가 그대로 넘어갈 수 있음)
                        e.preventDefault();
                        page(0);  <!-- 페이지 0번으로 세팅 -->
                  });
            });

            function page(page){
                  var searchDateType = $("#searchDateType").val();
                  var searchSellStatus = $("#searchSellStatus").val();
                  var searchBy = $("#searchBy").val();
                  var searchQuery = $("#searchQuery").val();

                  location.href="/admin/items/" + page + "?searchDateType=" + searchDateType
                          + "&searchSellStatus=" + searchSellStatus
                          + "&searchBy=" + searchBy
                          + "&searchQuery=" + searchQuery;
            }

      </script>
</th:block>
  • 상품 목록 테이블 부분
  • ${items} 변수는 Controller 에서 전달 받은 Page 객체
  • .getContent() 메소드를 이용하여 Page 객체의 content 부분을 추출
<form th:action="@{'/admin/items/' + ${items.number}}" role="form" method="get" th:object="${items}">
            <table class="table">
                  <thead>
                  <tr>
                        <td>상품아이디</td>
                        <td>상품명</td>
                        <td>상태</td>
                        <td>등록자</td>
                        <td>등록일</td>
                  </tr>
                  </thead>
                  <tbody>
                  <tr th:each="item, status: ${items.getContent()}">
                        <td th:text="${item.id}"></td>
                        <td>
                              <a th:href="'/admin/item/'+${item.id}" th:text="${item.itemNm}"></a>
                        </td>
                        <!-- 아래 문장에서 품절, 판매중이 정확하게 나오지 않는 경우엔 밑에 문장으로 변경하기 -->
                        <!--<td th:text="${item.itemSellStatus == 0} ? '품절' : '판매중'"></td>-->
                        <td th:text="${item.itemSellStatus == T(kr.spring.item.constant.ItemSellStatus).SELL} ? '판매중' : '품절'"></td>
                        <td th:text="${item.createdBy}"></td>
                        <td th:text="${item.regTime}"></td>
                  </tr>
                  </tbody>
            </table>
  • 하단 페이지 부분
  • 페이지 객체의 페이지 index 는 0부터 시작, 페이지 표시 번호는 1부터 시작
  • th:with 을 통해서 변수값을 정의start (페이지 시작 번호) : ((현재 페이지번호 / 보여줄 페이지 수) * 보여줄 페이지수) + 1end (페이지 끝 번호) : start + (보여줄 페이지 수 - 1)페이지의 총 개수가 0개면 end = 1, start + (보여줄 페이지 수 - 1) 보다 작다면 end = 페이지 총 개수
  • 첫 페이지 또는 마지막 페이지면 class 식별자를 추가(classappend) 하여 disabled 적용
  • 현재 페이지이면 active 클래스 추가
  • 페이지 번호를 클릭하면 위에 존재하는 스크립트의 page() 함수 수행
<!-- 부트 스트랩 사용할 때 재사용 가능 -->
            <div th:with="start=${(items.number/maxPage)*maxPage + 1}, end=(${(items.totalPages == 0) ? 1 : (start + (maxPage - 1) < items.totalPages ? start + (maxPage - 1) : items.totalPages)})" >
                  <ul class="pagination justify-content-center">

                        <li class="page-item" th:classappend="${items.first}?'disabled'">
                              <a th:onclick="'javascript:page(' + ${items.number - 1} + ')'" aria-label='Previous' class="page-link">
                                    <span aria-hidden='true'>Previous</span>
                              </a>
                        </li>

                        <li class="page-item" th:each="page: ${#numbers.sequence(start, end)}" th:classappend="${items.number eq page-1}?'active':''">
                              <a th:onclick="'javascript:page(' + ${page - 1} + ')'" th:inline="text" class="page-link">[[${page}]]</a>
                        </li>

                        <li class="page-item" th:classappend="${items.last}?'disabled'">
                              <a th:onclick="'javascript:page(' + ${items.number + 1} + ')'" aria-label='Next' class="page-link">
                                    <span aria-hidden='true'>Next</span>
                              </a>
                        </li>
                  </ul>
            </div>
  • 검색 조건 부분
  • ${itemSearchDto} 객체와 매핑
				<div class="form-inline justify-content-center" th:object="${itemSearchDto}">
                  <select th:field="*{searchDateType}" class="form-control" style="width:auto;">
                        <option value="all">전체기간</option>
                        <option value="1d">1일</option>
                        <option value="1w">1주</option>
                        <option value="1m">1개월</option>
                        <option value="6m">6개월</option>
                  </select>
                  <select th:field="*{searchSellStatus}" class="form-control" style="width:auto;">
                        <option value="">판매상태(전체)</option>
                        <option value="SELL">판매</option>
                        <option value="SOLD_OUT">품절</option>
                  </select>
                  <select th:field="*{searchBy}" class="form-control" style="width:auto;">
                        <option value="itemNm">상품명</option>
                        <option value="createdBy">등록자</option>
                  </select>
                  <input th:field="*{searchQuery}" type="text" class="form-control" placeholder="검색어를 입력해주세요">
                  <button id="searchBtn" type="submit" class="btn btn-primary">검색</button>
            </div>

3. 검색 조건 적용 결과화면