오늘은 axios를 활용하여 페이징처리를 진행할 것이다.
결과물은 아래와 같다!
- 한 페이지 당 총 6개의 데이터를 보여준다.
- 페이지 버튼은 5개씩 보여준다.
@RequestMapping("/productList/{categoryCode}")
public String productByCategory(@PathVariable("categoryCode") int categoryCode, Model model,
@CookieValue(value="productCnt", required=false) Cookie cookieCnt, HttpServletResponse response) {
//상품 총 갯수 쿠키에 저장
String cnt = Integer.toString(pm.getCount(categoryCode));
if (cookieCnt==null) {
cookieCnt = new Cookie("productCnt", cnt);
} else if (!cookieCnt.getValue().equals(cnt)) {
cookieCnt.setValue(cnt);
}
response.addCookie(cookieCnt);
return "/ProductList";
}
우선 상품리스트 페이지로 이동하게 되면 해당 카테고리의 상품들의 총 갯수를 카운트하고, 이를 쿠키에 저장했다.
(쿠키에 대해서 더 많은 설정을 해 줘야 하지만, 우선 여기서는 간단히 저장만 하도록 하겠다.)
var categoryCode = Number($(location).attr('pathname').slice(-1));
var totalPage = Math.ceil($.cookie("productCnt")/6);
var buttonHtml = "";
$(window).ready(function() {
var data = {"page":1, "categoryCode":categoryCode};
if (totalPage>5) {
for (var page=1; page<=5; page++) {
buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
}
buttonHtml += "<button id=\"nextButton\" type=\"button\" class=\"btn btn-light\">다음</button>";
} else {
for (var page=1; page<=totalPage; page++) {
buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
}
}
$("#pageButtonGroup").html(buttonHtml);
$(".pageButton").first().css({background:"black", color:"white"});
pagingProduct(data);
});
- categoryCode : 현재 상품 페이지의 카테고리 코드.
- totalPage : cookie에 저장한 전체 상품 갯수를 이용해 총 페이지를 계산한다.
- buttonHtml : 페이지 버튼과 관련된 html 코드.
$(document).on("click", ".pageButton", function() {
$(".pageButton").css({background:"#F8F9FA", color:"black"});
$(this).css({background:"black", color:"white"});
var page = Number($(this).text());
var data = {"page":page, "categoryCode":categoryCode};
pagingProduct(data);
});
$(document).on("click", "#nextButton", function() {
var data = {"page":Number($(".pageButton").last().text())+1,
"categoryCode":categoryCode};
buttonHtml = "<button id=\"prevButton\" type=\"button\" class=\"btn btn-light\">이전</button>";
if (totalPage>=data.page+5) {
for (var page=data.page; page<data.page+5; page++) {
buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
}
buttonHtml += "<button id=\"nextButton\" type=\"button\" class=\"btn btn-light\">다음</button>";
} else {
for (var page=data.page; page<=totalPage; page++) {
buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
}
}
$("#pageButtonGroup").html(buttonHtml);
$(".pageButton").first().css({background:"black", color:"white"});
pagingProduct(data);
});
$(document).on("click", "#prevButton", function() {
var data = {"page":Number($(".pageButton").first().text())-1,
"categoryCode":categoryCode};
buttonHtml = "";
if (data.page-5!=0) {
buttonHtml = "<button id=\"prevButton\" type=\"button\" class=\"btn btn-light\">이전</button>";
}
for (var page=data.page-4; page<=data.page; page++) {
buttonHtml += "<button type=\"button\" class=\"btn btn-light pageButton\" index=\"" + page + "\">" + page + "</button>";
}
buttonHtml += "<button id=\"nextButton\" type=\"button\" class=\"btn btn-light\">다음</button>";
$("#pageButtonGroup").html(buttonHtml);
$(".pageButton").last().css({background:"black", color:"white"});
pagingProduct(data);
});
이 함수는 axios를 활용해 서버에 인자로 받은 데이터를 호출하는 함수이다.
function pagingProduct(data) {
axios.post("/productList/paging", data).then(function(res) {
var html = "";
var imageSrc = "";
for (var i=0; i<res.data.length; i++) {
//서버에서 전달받은 데이터를 이용해 상품 리스트 관련 html 코드 작성
$("#productRow").html(html);
}).catch(function(error) {
alert("오류가 발생했습니다!");
if (error.response) {
// 요청이 이루어졌으며 서버가 2xx의 범위를 벗어나는 상태 코드로 응답했습니다.
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
// 요청이 이루어 졌으나 응답을 받지 못했습니다.
console.log(error.request);
} else {
// 오류를 발생시킨 요청을 설정하는 중에 문제가 발생했습니다.
console.log('Error', error.message);
}
console.log(error.config);
});
}
@RequestMapping(value="/productList/paging", method=RequestMethod.POST)
@ResponseBody
public List<ProductVO> productPaging(@RequestBody HashMap<String, Object> reqHm) {
//log.info(reqHm);
PageDTO page = new PageDTO(Integer.parseInt(reqHm.get("page").toString()), 6);
List<ProductVO> productVOList = pm.getListByCategory(page.getOffset(), Integer.parseInt(reqHm.get("categoryCode").toString()));
return productVOList;
}
해당 코드는 클라이언트에서 axios를 활용하여 POST 전송을 요청했을 때 서버에서 이뤄지는 Controller 클래스이다. 클라이언트를 통해 전달받은 데이터(reqHm)를 활용하여 해당 페이지의 상품 리스트 정보를 클라이언트에게 다시 전달한다.
여기에서 PageDTO라는 객체가 등장하는데, 이 객체는 페이지와 관련된 정보를 담고 있는 DTO 객체이다.
@Data
public class PageDTO {
private int page;
private int cntPerPage;
private int offset;
public PageDTO() {};
public PageDTO(int page, int cntPerPage) {
this.page = page;
this.cntPerPage = cntPerPage;
if (this.page==1) {
this.offset = 0;
} else {
this.offset = (page-1)*cntPerPage;
}
}
}
- page : 해당 페이지 번호.
- cntPerPage : 한 페이지에서 보여줄 데이터의 개수.(여기서는 6)
- offset : DB 조회 시 첫 시작 인덱스. (만약 2페이지의 상품 데이터를 검색할 경우 offset은 6이다.)
axios를 활용한 페이징 처리를 끝냈다..!
하지만 아직도 문제가 있다. 만약에 6페이지에 있는 상품리스트 중 하나를 클릭해 상세정보를 보고 뒤로 가게 되면 6페이지가 아닌 1페이지로 돌아간다. 또 새로고침을 해도 6페이지가 아니라 1페이지가 나온다... 이 문제를 어떻게 해결해야할지 아시는 분이 있다면 꼭 댓글 부탁드립니다...!!!