Spring/Maven Project

Spring에 Pagination(페이지네이션) 처리 및 적용 3

carrotweb 2023. 1. 1. 23:11
728x90
반응형

페이지네이션에서 전체 페이지 앞 번호 버튼, 이전 페이지 사이즈 번호 버튼, 다음 페이지 사이즈 번호 버튼, 전체 페이지 마지막 번호 버튼을 활성화 또는 비활성화로 제어하면 클릭에 대한 오류를 방지할 수 있습니다. (이미 내부 소스에서 예외처리가 되어 있어 오류는 발생하지 않습니다.)

 

 

페이지네이션에서 버튼은 <button> 태그가 아닌 <li> 태그와 <a> 태그를 사용하고 있습니다.

 

<button disabled>

<button> 태그는 비활성화하기 위해서 disable 속성을 추가하면 되지만 <li> 태그와 <a> 태그는 disable 속성이 지원되지 않습니다.

 

참고로 <a> 태그를 비활성화하기 위해서는 일반적으로 href 속성을 제거합니다.

<li class="page-item"><a class="page-link page-first" data-pageno="1" href="javascript:void(0)">First</a></li>

<!-- href 속성 제거를 통한 비활성화 처리 -->
<li class="page-item"><a class="page-link page-first" data-pageno="1">First</a></li>

그러나 <a> 태그를 화성화/비활성화하기 위해서는 Script에서 동적으로 href 속성을 제거했다가 추가해야 하는 문제점이 있습니다.

 

현재 페이지네이션에서 <a> 태그들은 href 속성 값이 void로 처리되어 있고 Script에서 <a> 태그들에 대한 클릭 이벤트를 공통으로 처리하고 있기 때문에 href 속성 제거 없이 Script에서 처리할 수 있습니다.

 

 

Script로 처리하기

 

페이지레이션 Script에 있는 클릭 이벤트 함수를 수정하겠습니다.

$('#boardPagination .page-link').click(function(event) {
	event.preventDefault();
	event.stopPropagation();
	boardSearch.find('input:hidden[name="paging.pageNo"]').val($(this).attr("data-pageno"));
	boardSearch.submit();
});

 

1. 먼저 전체 페이지 마지막 번호를 Script에서 사용할 수 있게 <form:form> 태그 안에 <form:hidden> 태그를 생성하고 path 속성에 boardSearch 객체에서 pagination 객체의 pageLastNo 변수를 지정합니다.

<form:hidden path="pagination.pageLastNo" />
그리고 Script에 변수로 가져옵니다.
var pageLastNo = boardSearch.find('input:hidden[name="pagination.pageLastNo"]').val();

 

2. 현재 페이지 번호와 이동할 페이지 번호를 변수로 가져옵니다.

var pageNo = boardSearch.find('input:hidden[name="pagination.pageNo"]').val();
var moveToPageNo = $(this).attr("data-pageno");

 

3. 현제 페이지 번호와 이동할 페이지 번호가 1 이거나 현제 페이지 번호와 이동할 페이지 번호가 전체 페이지 마지막 번호이면 이동하지 않게 리턴합니다.

if ((pageNo == 1 && moveToPageNo == 1) || (pageNo == pageLastNo && moveToPageNo == pageLastNo)) {
	return;
}

추가로 현제 페이지 번호와 이동할 페이지 번호가 같을 때도 이동하지 않게 하고 싶다면 조건문에 추가하면 됩니다.

if ((pageNo == moveToPageNo) || (pageNo == 1 && moveToPageNo == 1) || (pageNo == pageLastNo && moveToPageNo == pageLastNo)) {
	return;
}

 

수정된 클릭 이벤트 함수입니다.

$('#boardPagination .page-link').click(function(event) {
	event.preventDefault();
	event.stopPropagation();
	var pageLastNo = boardSearch.find('input:hidden[name="pagination.pageLastNo"]').val();
	var pageNo = boardSearch.find('input:hidden[name="pagination.pageNo"]').val();
	var moveToPageNo = $(this).attr("data-pageno");
	if ((pageNo == moveToPageNo) || (pageNo == 1 && moveToPageNo == 1) || (pageNo == pageLastNo && moveToPageNo == pageLastNo)) {
		return;
	}
	if (moveToPageNo > 0 && moveToPageNo <= pageLastNo) {
		boardSearch.find('input:hidden[name="pagination.pageNo"]').val(moveToPageNo);
		boardSearch.submit();
	}
});

 

수정된 클릭 이벤트 함수는 페이지레이션 버튼의 클릭 이벤트를 제어했다기보다는 조건문으로 이동하지 않게 처리한 겁니다. 그래서 페이지레이션 버튼 자체를 활성화하거나 비활성화할 수는 없습니다.

 

 

그래서 페이지레이션 버튼 자체를성화하거나 비활성화할 수는 있는 방법을 알아보겠습니다.

 

 

CSS의 pointer-events 속성으로 처리하기

 

그것은 CSS의 pointer-events 속성을 사용하여 이벤트에 대해 반응해야 하는지 여부를 설정할 수 있습니다.

pointer-events: auto|none;

auto는 이벤트에 대해 반응하게 하고 none은 이벤에 대해 반응하지 않게 합니다.

none으로 설정되면 마우스의 커서가 텍스트 커서로 변경됩니다.

 

위에 있는 Script로 테스트하셨다면 기존 소스로 다시 변경하시기 바랍니다.

 

1. <style> 태그에 페이지네이션 버튼인 <li> 태그가 이벤트에 대해 반응하지 않게 pointer-events 속성을 none으로 설정하고 <a> 태그의 폰트 색을 회색으로 변경하기 위해 CSS를 추가합니다.

.board ul.pagination li.disabled { pointer-events: none; }
.board ul.pagination li.disabled a { color: #cccccc; }

 

2. pagination UI를 수정합니다.

  1. 전체 페이지 앞 번호인 <li> 태그의 class 속성 값에 현재 페이지 번호(pageNo)가 1 이면 disabled를 추가합니다.
  2. 이전 페이지 사이즈 번호인 <li> 태그의 class 속성 값에 페이지 시작 번호(pageStartNo)에서 1을 뺀 값이 0 이면 disabled를 추가합니다.
  3. 다음 페이지 사이즈 번호인 <li> 태그의 class 속성 값에 페이지 종료 번호(pageEndNo)에서 1을 더한 값이 페이지 마지막 번호(pageLastNo) 보다 크면 disabled를 추가합니다.
  4. 전체 페이지 마지막 번호인 <li> 태그의 class 속성 값에 현재 페이지 번호(pageNo)가 페이지 마지막 번호(pageLastNo)와 같으면 disabled를 추가합니다.

 

<c:if test="${not empty boardList}">
	<div>
		<ul id="boardPagination" class="pagination">
			<li class="page-item<c:if test="${boardSearch.pagination.pageNo == 1}"> disabled</c:if>"><a class="page-link page-first" data-pageno="1" href="javascript:void(0)">First</a></li>
			<li class="page-item<c:if test="${(boardSearch.pagination.pageStartNo - 1) == 0}"> disabled</c:if>"><a class="page-link page-prev" data-pageno="${boardSearch.pagination.pageStartNo - 1}" href="javascript:void(0)">&lt;</a></li>
			<c:forEach var="page" begin="${boardSearch.pagination.pageStartNo}" end="${boardSearch.pagination.pageEndNo}" step="1">
				<li class="page-item<c:if test="${boardSearch.pagination.pageNo == page}"> active</c:if>">
					<a class="page-link page-no" data-pageno="${page}" href="javascript:void(0)">${page}</a>
				</li>
			</c:forEach>
			<li class="page-item<c:if test="${boardSearch.pagination.pageEndNo + 1 > boardSearch.pagination.pageLastNo}"> disabled</c:if>"><a class="page-link page-next" data-pageno="${boardSearch.pagination.pageEndNo + 1}" href="javascript:void(0)">&gt;</a></li>
			<li class="page-item<c:if test="${boardSearch.pagination.pageNo == boardSearch.pagination.pageLastNo}"> disabled</c:if>"><a class="page-link page-last" data-pageno="${boardSearch.pagination.pageLastNo}" href="javascript:void(0)">Last</a></li>
		</ul>
	</div>
</c:if>

 

 

Maven Spring Project를 실행하여 웹 브라우저로 확인하기

 

1. "Servers"탭에서 "Tomcat9"를 선택하고 "start"버튼(start the server)을 클릭하면 Tomcat이 실행됩니다.

 

2. 웹 브라우저에서 "http://localhost:9000/index.do"를 입력하고 페이지 크기를 10에서 5로 변경합니다.

그러면 페이지네이션에 처음 페이지로 이동하는 버튼과 이전/다음 페이지로 이동하는 버튼이 비활성화되어 나타나는 것을 확인할 수 있습니다.

 

3. 2번 페이지 번호를 클릭하면 이전/다음 페이지로 이동하는 버튼과 마지막 페이지로 이동하는 버튼이 비활성화되어 나타나는 것을 확인할 수 있습니다.

 

현재 이전/다음 페이지로 이동하는 버튼 항상 비활성화되어 있는 이유는 이전 페이지로 이동하는 번호가 0이고 다음 페이지로 이동하는 번호가 3으로 더 이상 이동할 수 없기 때문입니다.

 

4. 웹 브라우저에서 "http://localhost:9000/index.do?pagination.recordCountPerPage=1&pagination.pageSize=3"로 입력하여 페이지레이션 버튼을 클릭해 보면 이전/다음 페이지로 이동하는 버튼 활성화되고 비활성화되는 것을 확인할 수 있습니다.

 

페이지레이션의 버튼을 비활성화시키기 위해서는 복잡하지 않지만 연산해야서 비교 처리해야 합니다.

 

그래서 페이지 연산과 버튼의 활성화 여부를 Pagination 객체에서 처리하여 Pagination UI에서는 연산 없이 값만 사용하여 처리할 수 있게 하겠습니다.

 

 

Pagination 확장 처리

 

이전 페이지 사이즈 번호(prevPageSizeNo)는 페이지 시작 번호(pageStartNo)에서 1을 뺍니다.

이전 페이지 사이즈 번호 활성화 여부(enablePrevPageSizeNO)는 이전 페이지 사이즈 번호(prevPageSizeNo)가 0보다 크면 이동할 수 있기 때문에 true로 설정합니다.

int prevPageSizeNo = 0;
boolean enablePrevPageSizeNo = false;

prevPageSizeNo = pageStartNo - 1;
if (prevPageSizeNo > 0) {
	enablePrevPageSizeNo = true;
}

 

다음 페이지 사이즈 번호(nextPageSizeNo)는 페이지 종료 번호(pageEndNo)에 1을 더합니다.

다음 페이지 사이즈 번호 활성화 여부(enableNextPageSizeNO)는 페이지 마지막 번호(pageLastNo) 보다 작거나 같으면 이동할 수 있기 때문에 true로 설정합니다.

int nextPageSizeNo = 1;
boolean enableNextPageSizeNo = false;

nextPageSizeNo = endPageNo + 1;
if (nextPageSizeNo <= pageLastNo) {
	enableNextPageSizeNo = true;
}

 

전체 페이지 앞 번호 활성화 여부(enablePageFirstNo) 현재 페이지 번호(pageNo)가 1보다 크면 이동할 수 있기 때문에 true로 설정합니다.

boolean enablePageFirstNo = false;

if (pageNo > 1) {
	enablePageFirstNo = true;
}

 

전체 페이지 마지막 번호 활성화 여부(enablePageLastNo) 현재 페이지 번호(pageNo)가 페이지 마지막 번호(pageLastNo) 보다 작으면 이동할 수 있기 때문에 true로 설정합니다.

boolean enablePageLastNo = false;

if (pageNo < pageLastNo) {
	enablePageLastNo = true;
}

 

 

 

Maven Spring Project에 Common Pagination 수정하기

 

1. Java Resource > src/main/java에 com.home.study.common.search 패키지에 있는 Pagination.java 파일을 오픈하고 수정합니다.

  1. 이전 페이지 사이즈 번호(prevPageSizeNo), 다음 페이지 사이즈 번호(nextPageSizeNo), 이전 페이지 사이즈 번호 활성화 여부(enablePrevPageSizeNo), 다음 페이지 사이즈 번호 활성화 여부(enableNextPageSizeNo), 전체 페이지 앞 번호 활성화 여부(enablePageFirstNo), 전체 페이지 마지막 번호 활성화 여부(enablePageLastNo) 변수를 생성하고 Getter, Setter를 생성합니다.
  2. process() 메서드에 계산 공식을 추가합니다.
package com.home.study.common.search;

public class Pagination extends Paging {

	/**
	 * serialVersionUID
	 */
	private static final long serialVersionUID = 1014943426267041010L;

	/**
	 * 페이지 사이즈(기본값 10)
	 */
	private int pageSize = 10;

	/**
	 * 페이지 시작 번호
	 */
	private int pageStartNo = 1;

	/**
	 * 페이지 종료 번호
	 */
	private int pageEndNo = 1;

	/**
	 * 이전 페이지 사이즈 번호
	 */
	private int prevPageSizeNo = 1;

	/**
	 * 다음 페이지 사이즈 번호
	 */
	private int nextPageSizeNo = 1;

	/**
	 * 이전 페이지 사이즈 번호 활성화 여부
	 */
	private boolean enablePrevPageSizeNo = false;

	/**
	 * 다음 페이지 사이즈 번호 활성화 여부
	 */
	private boolean enableNextPageSizeNo = false;

	/**
	 * 전체 페이지 앞 번호 활성화 여부
	 */
	private boolean enablePageFirstNo = false;

	/**
	 * 전체 페이지 마지막 번호 활성화 여부
	 */
	private boolean enablePageLastNo = false;

	/**
	 * 페이지 사이즈를 가져옵니다.
	 * @return 페이지 사이즈
	 */
	public int getPageSize() {
		return pageSize;
	}

	/**
	 * 페이지 사이즈를 설정합니다.
	 * @param pageSize 페이지 사이즈
	 */
	public void setPageSize(int pageSize) {
		if (pageSize <= 0) {
			pageSize = 10;
		}
		this.pageSize = pageSize;
	}

	/**
	 * 페이지 시작 번호를 가져옵니다.
	 * @return 페이지 시작 번호
	 */
	public int getPageStartNo() {
		return pageStartNo;
	}

	/**
	 * 페이지 종료 번호를 가져옵니다.
	 * @return 페이지 종료 번호
	 */
	public int getPageEndNo() {
		return pageEndNo;
	}

	@Override
	protected void process(boolean zero) {
		super.process(zero);
		
		// 페이지 시작 번호 설정
		// 몫만큼 페이지 시작 번호 변경한다.
		int start = pageNo / pageSize;
		if (start >= 1) {
			// 나머지가 없으면 페이지 번호가 페이지 마지막 번호와 같아 몫을 감소 시킨다.
			if (pageNo % pageSize == 0){
				start--;
			}
			pageStartNo = (start * pageSize) + 1;
		}
		
		if (pageLastNo > 0) {
			// 페이지 종료 번호 설정
			pageEndNo = (pageStartNo - 1) + pageSize;
			// 페이지 종료 번호가 페이지 마지막 번호보다 크면 페이지 마지막 번호로 변경
			if (pageEndNo > pageLastNo) {
				pageEndNo = pageLastNo;
			}
			
			// 이전 페이지 사이즈 번호
			prevPageSizeNo = pageStartNo - 1;
			// 이전 페이지 사이즈 번호 활성화 여부
			if (prevPageSizeNo > 0) {
				enablePrevPageSizeNo = true;
			}
			
			// 다음 페이지 사이즈 번호
			nextPageSizeNo = pageEndNo + 1;
			// 다음 페이지 사이즈 번호 활성화 여부
			if (nextPageSizeNo <= pageLastNo) {
				enableNextPageSizeNo = true;
			}
			
			// 전체 페이지 앞 번호 활성화 여부
			if (pageNo > 1) {
				enablePageFirstNo = true;
			}
			
			// 전체 페이지 마지막 번호 활성화 여부
			if (pageNo < pageLastNo) {
				enablePageLastNo = true;
			}
		}
	}

	/**
	 * 이전 페이지 사이즈 번호를 가져옵니다.
	 * @return 이전 페이지 사이즈 번호
	 */
	public int getPrevPageSizeNo() {
		return prevPageSizeNo;
	}

	/**
	 * 다음 페이지 사이즈 번호를 가져옵니다.
	 * @return 다음 페이지 사이즈 번호
	 */
	public int getNextPageSizeNo() {
		return nextPageSizeNo;
	}

	/**
	 * 이전 페이지 사이즈 번호 활성화 여부를 가져옵니다.
	 * @return 이전 페이지 사이즈 번호 활성화 여부
	 */
	public boolean isEnablePrevPageSizeNo() {
		return enablePrevPageSizeNo;
	}

	/**
	 * 다음 페이지 사이즈 번호 활성화 여부를 가져옵니다.
	 * @return 다음 페이지 사이즈 번호 활성화 여부
	 */
	public boolean isEnableNextPageSizeNo() {
		return enableNextPageSizeNo;
	}

	/**
	 * 전체 페이지 앞 번호 활성화 여부를 가져옵니다.
	 * @return 전체 페이지 앞 번호 활성화 여부
	 */
	public boolean isEnablePageFirstNo() {
		return enablePageFirstNo;
	}

	/**
	 * 전체 페이지 마지막 번호 활성화 여부를 가져옵니다.
	 * @return 전체 페이지 마지막 번호 활성화 여부
	 */
	public boolean isEnablePageLastNo() {
		return enablePageLastNo;
	}
}

 

 

Maven Spring Project의 main.jsp에 Pagination UI 수정하기

 

1. /src/main/webapp/WEB-INF/views/main/main.jsp 파일을 오픈하여 pagination UI를 수정합니다.

  1. 전체 페이지 앞 번호인 <li> 태그의 class 속성 값에 전체 페이지 앞 번호  활성화 여부(enablePageFirstNo)를 비교하여 disabled를 추가합니다.
  2. 이전 페이지 사이즈 번호인 <li> 태그의 데이터 속성(data-pageno) 값을 이전 페이지 사이즈 번호(prevPageSizeNo)로 변경하고 class 속성 값에 이전 페이지 사이즈 번호 활성화 여부(enablePrevPageSizeNo)를 비교하여 disabled를 추가합니다.
  3. 다음 페이지 사이즈 번호인 <li> 태그의 데이터 속성(data-pageno) 값을 다음 페이지 사이즈 번호(nextPageSizeNo)로 변경하고 class 속성 값에 다음 페이지 사이즈 번호 활성화 여부(enableNextPageSizeNo)를 비교하여 disabled를 추가합니다.
  4. 전체 페이지 마지막 번호인 <li> 태그의 class 속성 값에 전체 페이지 마지막 번호 활성화 여부(enablePageLastNo)를 비교하여 disabled를 추가합니다.
<c:if test="${not empty boardList}">
	<div>
		<ul id="boardPagination" class="pagination">
			<li class="page-item<c:if test="${!boardSearch.pagination.isEnablePageFirstNo()}"> disabled</c:if>"><a class="page-link page-first" data-pageno="1" href="javascript:void(0)">First</a></li>
			<li class="page-item<c:if test="${!boardSearch.pagination.isEnablePrevPageSizeNo()}"> disabled</c:if>"><a class="page-link page-prev" data-pageno="${boardSearch.pagination.prevPageSizeNo}" href="javascript:void(0)">&lt;</a></li>
			<c:forEach var="page" begin="${boardSearch.pagination.pageStartNo}" end="${boardSearch.pagination.pageEndNo}" step="1">
				<li class="page-item<c:if test="${boardSearch.pagination.pageNo == page}"> active</c:if>">
					<a class="page-link page-no" data-pageno="${page}" href="javascript:void(0)">${page}</a>
				</li>
			</c:forEach>
			<li class="page-item<c:if test="${!boardSearch.pagination.isEnableNextPageSizeNo()}"> disabled</c:if>"><a class="page-link page-next" data-pageno="${boardSearch.pagination.nextPageSizeNo}" href="javascript:void(0)">&gt;</a></li>
			<li class="page-item<c:if test="${!boardSearch.pagination.isEnablePageLastNo()}"> disabled</c:if>"><a class="page-link page-last" data-pageno="${boardSearch.pagination.pageLastNo}" href="javascript:void(0)">Last</a></li>
		</ul>
	</div>
</c:if>

 

2. <style> 태그에 현재 페이지 번호 버튼이 활성화(active)될 때 이벤트에 대해 반응하지 않게 pointer-events 속성을 none으로 추가합니다.

 

.board ul.pagination li.page-item.active a { color: #fff; background-color: #0d6efd; pointer-events: none; }

 

 

Maven Spring Project를 실행하여 웹 브라우저로 확인하기

 

1. "Servers"탭에서 "Tomcat9"를 선택하고 "start"버튼(start the server)을 클릭하면 Tomcat이 실행됩니다.

 

2. 웹 브라우저에서 "http://localhost:9000/index.do"를 입력하고 페이지 크기를 10에서 5로 변경합니다.

 

728x90
반응형