[DIOS] 쇼핑몰 리뷰 < Paging | Pagination > 구현

오늘은 리뷰페이징에 대해 기록 해보자 !

지난번에 포스팅한 목록페이징 같은 경우엔, list.html 그 자체에서 상품을 가져올때 페이징처리 해주고 html 타임리프 사용해서 넣어주면 끝이였는데,  이번에 리뷰페이징은 컨트롤러에서 애초에 JSON타입으로 값을 보내주기도 했고, 상품 읽기 페이지 안에 자바스크립트로 반복문을 실행하면서 리뷰를 가져오는거라 페이징 처리에 접근하기가 조금 난감했는데, 강사님께 여쭤보니 javaScript xhr 로 페이징을 해야한다는 힌트를얻고 시작 !


<Models/PagingModel> : 페이징 처리하기위해 필요한 모델 패키지/컨트롤러 생성 후 변수 3개 받았을때 처리할 메서드 만들기

public PagingModel(int countPerPage, int totalCount, int requestPage) {
    this.countPerPage = countPerPage;
    this.totalCount = totalCount;
    this.requestPage = requestPage;
    this.minPage = 1;
    this.maxPage = (totalCount - 1) / countPerPage + 1;
    this.startPage = ((requestPage - 1) / countPerPage) * countPerPage + 1;
    this.endPage = Math.min(startPage +(countPerPage-1), maxPage);
}

<Controller> :현재페이지를 매개변수로 받고, 한페이지당 가져올 갯수만큼 페이징 한 뒤 JSON형식으로 값 보내기

@GetMapping(value = "review", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String getReview(@RequestParam(value = "gid") int goodsIndex,
                        @RequestParam(value = "page", required = false, defaultValue = "1") Integer page) throws JsonProcessingException {

    if (page == null) {
        page = 1;
    }
    ////////////////// pagination ///////////
    page = Math.max(1, page);
    int totalCount = this.goodsService.getReviewCount(goodsIndex);
    PagingModel paging = new PagingModel(5, totalCount, page);
    ObjectMapper objectMapper = new ObjectMapper();
    JSONObject responseJson = new JSONObject();
    responseJson.put("currentPage", page);
    responseJson.put("startPage", paging.startPage);
    responseJson.put("endPage", paging.endPage);
    responseJson.put("maxPage", paging.maxPage);
    responseJson.put("minPage", paging.minPage);
    responseJson.put("reviews", new JSONArray(objectMapper.writeValueAsString(this.goodsService.getReviewsPaging(goodsIndex, paging))));
    return responseJson.toString();
}

이렇게 하면 컨트롤러에서

{"currentPage":?,

"startPage":?,

"endPage":?,

"maxPage":?,

"minPage":?,

"reviews":{"index":?,

                   "userEmail":?,

                   "itemIndex":?,

                   ...}

}

이런 형태로 값을 보내게 된다.


그래서 이 값들을 javaScript ajax 요청할때

const responseObject = JSON.parse(xhr.responseText);
for (const reviewObject of responseObject['reviews']) {

이렇게 Object로 가져오고, 마지막 배열로된 reviews에 관련된 정보들은 반복문으로 돌려서 사용한다.

이 값들을 이용해 이제 JS 에서 페이징 태그를 만들어낼건데, domParser 형식으로 가져오려고 하니 html 구문을 반복문 돌리는 문제가 있어서 하나하나씩 쌓아주는 방식을 선택했다. 

pageContainer.innerHTML = '';

if (responseObject['reviews'].length > 0) { //리뷰가 존재한다면

    const minPageElement = document.createElement('a');
    minPageElement.setAttribute('class', 'page');
    
    const minPageIconElement = document.createElement('i');
    minPageIconElement.setAttribute('class', 'fa-solid fa-angles-left');
    minPageElement.append(minPageIconElement);
    minPageElement.addEventListener('click', () => {
        loadReviews(responseObject['minPage']);
    })
    if (responseObject['currentPage'] > responseObject['minPage']) {
        pageContainer.append(minPageElement);
    }

    const prevPageElement = document.createElement('a');
    prevPageElement.setAttribute('class', 'page');

    const prevPageIconElement = document.createElement('i');
    prevPageIconElement.setAttribute('class', 'fa-solid fa-angle-left');
    prevPageElement.append(prevPageIconElement);
    prevPageElement.addEventListener('click', () => {
        loadReviews(responseObject['currentPage'] - 1);
    })
    if (responseObject['currentPage'] > responseObject['minPage']) {
        pageContainer.append(prevPageElement);
    }

    let numberPageElement = {};
    for (let i = responseObject['minPage']; i <= responseObject['maxPage']; i++) {
        numberPageElement[`numberPageElement${i}`] = document.createElement('a');
        numberPageElement[`numberPageElement${i}`].setAttribute('class', 'page');
        if(responseObject['currentPage'] === i){
            numberPageElement[`numberPageElement${i}`].classList.add('selected');
        }
        numberPageElement[`numberPageElement${i}`].innerText = i;
        numberPageElement[`numberPageElement${i}`].addEventListener('click', () => {
            loadReviews(i);
        });
        pageContainer.append(numberPageElement[`numberPageElement${i}`]);
    }

    const nextPageElement = document.createElement('a');
    nextPageElement.setAttribute('class', 'page');
    
    const nextPageElementIconElement = document.createElement('i');
    nextPageElementIconElement.setAttribute('class', 'fa-solid fa-angle-right');
    nextPageElement.append(nextPageElementIconElement);
    nextPageElement.addEventListener('click', () => {
        loadReviews(responseObject['currentPage'] + 1);
    })
    if(responseObject['currentPage'] < responseObject['maxPage']) {
        pageContainer.append(nextPageElement);
    }

    const maxPageElement = document.createElement('a');
    maxPageElement.setAttribute('class', 'page');

    const maxPageElementIconElement = document.createElement('i');
    maxPageElementIconElement.setAttribute('class', 'fa-solid fa-angles-right');
    maxPageElement.append(maxPageElementIconElement);
    maxPageElement.addEventListener('click', () => {
        loadReviews(responseObject['maxPage']);
    })
    if(responseObject['currentPage'] < responseObject['maxPage']) {
        pageContainer.append(maxPageElement);
    }
} else {
    pageContainer.innerText = '작성된 리뷰가 없습니다. \n\n 리뷰를 작성해주세요.';
}

 

이렇게 처리 후 css도 작성해주면

리뷰페이징 완료 !

더 좋은 방법이 있으면 댓글로 알려주세요 ~!~!

'개발 > Project' 카테고리의 다른 글

[DIOS] 상품 삭제  (0) 2023.06.18
[DIOS] 상품 수정 페이지  (0) 2023.06.18
[DIOS] 상품 읽기 페이지  (0) 2023.05.11
[DIOS] 상품 등록 페이지  (2) 2023.02.25
[DIOS] 게시판 비밀댓글 구현  (3) 2023.01.18