댓글기능 2 목록 요청작업

handlebars 기능 추가

<!-- 자바스크립트 handlebas 최신 -->
<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
handlebars 연습

동작은 안됨

https://jsfiddle.net/eu81273/Lqg0yrve/ 참조

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>

<script id="demo-template" type="text/x-handlebars-template">
<table>
	<thead>
		<th>이름</th>
		<th>아이디</th>
		<th>메일주소</th>
	</thead>
	<tbody>
		
		<tr>
			<td></td>
			<td></td>
			<td></td>
		</tr>
		
	</tbody>
</table>
</script>

<script>
// 핸들바 템플릿 가져오기
let source = $("#demo-template").html();

// 핸들바 템플릿 컴파일
let template = Handlebars.compile(source); 

//핸들바 템플릿에 바인딩할 데이터
// 데이터. 실제작업은 스프링에서 JSON형식으로 받을 것
let data = {
		users: [
			{name:"홍길동1", id:"user01", email:"user01@abc.com"},
			{name:"홍길동2", id:"user02", email:"user02@abc.com"},
			{name:"홍길동3", id:"user03", email:"user03@abc.com"},
			{name:"홍길동4", id:"user04", email:"user04@abc.com"},
			{name:"홍길동5", id:"user05", email:"user05@abc.com"}
		]
};

// 핸들바 템플릿에 데이터를 바인딩해서 HTML 생성
let html = template(data);

// 생성된 HTML을 DOM에 주입
$("body").append(html);
</script>

</head>
<body>

</body>
</html>
ReplyController RestAPI 활용 주소 넣기
// 1) 댓글목록데이터, 2) 페이징정보를 JSON포맷으로 클라이언트에게 리턴해주는 작업
// 주소 : /pages/{bno}/{page}. 주소의 일부분을 파라미터값으로 사용하고자 할 경우
// 예> /page/1/1
@GetMapping(value = "/pages/{bno}/{page}", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE})
public ResponseEntity<Map<String, Object>> getList(@PathVariable("page") int page,@PathVariable("bno") Long bno){
    ResponseEntity<Map<String, Object>> entity = null;
    Map<String, Object> map = new HashMap<String, Object>();

    // 1) 댓글목록 작업

    // 2) 페이징정보 작업


    return entity;
}

ReplyMapper.xml에 SQL 구문 작업
	<select id="getListWithPaging" resultType="com.demo.domain.ReplyVO">
		<![CDATA[ 
		SELECT RN, RNO, BNO, REPLY, REPLYER, REPLYDATE, UPDATEDATE
		FROM (
		    SELECT  /*+ INDEX_DESC(TBL_REPLY PK_REPLY)*/ ROWNUM RN, RNO, BNO, REPLY, REPLYER, REPLYDATE, UPDATEDATE FROM TBL_REPLY
		    WHERE  BNO = #{bno} AND ROWNUM <= (#{cri.pageNum} * #{cri.amount})
		)
		WHERE RN > ((#{cri.pageNum}-1) * #{cri.amount})
		]]>
	</select>
	
	<select id="getCountByBno" resultType="int">
		select count(*) from TBL_REPLY where bno = #{bno}
	</select>

ReplyMapper 인터페이스
	// Criteria cri : 페이징파라미터, Long bno : 게시판글번호(본문글)
	// MAPPER INTERFACE의 메서드 파라미터가 2개이상일 경우 @Param 어노테이션을 사용해야 한다.(중요)
	List<ReplyVO> getListWithPaging(@Param("cri") Criteria cri, @Param("bno") Long bno);
	
	// 본문글을 참조하는 댓글 데이터 개수
	int getCountByBno(Long bno);

이후 2개의 메서드를 하나씩 서비스로 보내도 되지만 같은 속성을 묶어서 진행한다

ReplyPageDTO domain 생성
package com.demo.domain;

import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor // 모든 필드를 파라미터로 하는 생성자메서드
public class ReplyPageDTO {

	private int replyCnt;
	private List<ReplyVO> list;
	
	// @AllArgsConstructor 으로 인해 아래것이 만들어짐
//	public ReplyPageDTO(int replyCnt, List<ReplyVO> list) {
//	
//		this.replyCnt = replyCnt;
//		this.list = list;
//	}
}

이후 Service에 하나로 메서드를 가져온다

ReplyPageDTO getListPage(Criteria cri, Long bno);

이후 ReplyServiceImpl에 하나로 등록

@Override
	public ReplyPageDTO getListPage(Criteria cri, Long bno) {
		// TODO Auto-generated method stub
		return new ReplyPageDTO(mapper.getCountByBno(bno), mapper.getListWithPaging(cri, bno));
	}

다시 컨트롤러에서 받아와서 jsp로 전달해준다

//1)댓글목록데이타, 2)페이징정보를 JSON포맷으로 클라이언트에게 리턴해주는 작업
	// 주소: /pages/{bno}/{page}. 주소의 일부분을 파라미터값으로 사용하고자 할경우
	// 예>  /pages/5120/1
	// 테스트주소:  http://localhost:9090/replies/pages/5120/1.json
	@GetMapping(value = "/pages/{bno}/{page}", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_UTF8_VALUE})
	public ResponseEntity<Map<String, Object>> getList(@PathVariable("bno") Long bno, @PathVariable("page") int page){
		ResponseEntity<Map<String, Object>> entity = null;
		Map<String, Object> map = new HashMap<String, Object>();
		
		//1)댓글목록작업. 클릭된 번호 page
		Criteria cri = new Criteria(page, 5);
		ReplyPageDTO replyObj = service.getListPage(cri, bno);
			
		map.put("list", replyObj.getList());
		
		//2)페이징정보작업
		PageDTO pageDTO = new PageDTO(cri, replyObj.getReplyCnt());
		map.put("pageMaker", pageDTO);
		
		entity = new ResponseEntity<Map<String,Object>>(map, HttpStatus.OK);
				
		return entity;
	}

더미데이터 넣고 확인하기 bno는 자기가 넣을 댓글 글번호

-- 댓글 더미데이터 삽입
INSERT INTO TBL_REPLY(rno, BNO, REPLY, REPLYER)
SELECT SEQ_REPLY.NEXTVAL, BNO, REPLY, REPLYER FROM TBL_REPLY WHERE BNO = 2163;

-- 더미데이터 확인
SELECT RNO, BNO, REPLY, REPLYER FROM TBL_REPLY WHERE BNO = 2163;

이후 postman에서 확인해보기

get.jsp 댓글목록 요청작업
    <script>
      // 댓글목록 요청작업(댓글+페이징기능)
      let bno = ${board.bno};  //본문 글번호
      let replyPage = 1;

      let url = "/replies/pages/" + bno + "/" + replyPage + ".json"; // 댓글목록및 페이징정보 요청주소

      getPage(url);

      //댓글목록출력작업
      //파라미터 설명
      /*
      replyData : 댓글목록 데이타, target : 댓글이 삽입될 태그위치, templateObj : 핸들바 템플릿 참조객체
      */
      let printData = function(replyData, target, templateObj) {
        
        let template = Handlebars.compile(templateObj.html());
        let html = template(replyData);
        target.empty();
        target.append(html);
      }


      //ajax구문으로 요청하는 작업.
      function getPage(url){
		    console.log(url);
        $.getJSON(url, function(data){

          //console.log(data);
          /*
            data.list : 댓글목록데이타, data.pageMaker : 댓글페이징정보
          */

          printData(data.list, $("#replyList"), $("#reply-template"));


        });


        //댓글목록 출력기능 함수

        //댓글페이징출력기능 함수

      }


    </script>
handlebar template : 목록작업
  <script id="reply-template" type="text/x-handlebars-template">
    
    <div class="form-group">
      <label for="replyer">작성자</label>
      <input type="hidden" id="rno" name="rno" value="">
      <input type="text" class="form-control" id="replyer" value="" readonly>
    </div>
    <div class="form-group">
      <label for="reply">등록일: </label>
      <textarea class="form-control" id="reply" rows="3" readonly></textarea>
    </div>
    
  </script>

<!-- 등록일 앞에 날짜표시넣기 핸들바 -->
  <script>
    //사용자정의 Helper. 용도: 댓글 작성일 밀리세컨드 데이타를 날짜포맷을 변환(2022/06/27)
    Handlebars.registerHelper("prettifyDate", function(timeValue){

      const date = new Date(timeValue);
      return date.getFullYear() + "/" +date.getMonth() + "/" + date.getDate();
    });
  </script>
댓글 페이징 출력작업 추가

자바스크립트 작업과 그에 해당하는 폼에 넣기

댓글페이징 출력 폼을 기준으로 작성

<!-- 댓글 페이징 출력-->
      <div id="replyPaging">
        
      </div>

댓글작업 자바스크립트 추가

<script>
      // 댓글목록 요청작업(댓글+페이징기능)
      let bno = ${board.bno};  //본문 글번호
      let replyPage = 1;

      let url = "/replies/pages/" + bno + "/" + replyPage + ".json"; // 댓글목록및 페이징정보 요청주소

      getPage(url);

      // 1) 글목록출력작업
      //파라미터 설명
      /*
      replyData : 댓글목록 데이타, target : 댓글이 삽입될 태그위치, templateObj : 핸들바 템플릿 참조객체
      */
      let printData = function(replyData, target, templateObj) {
        
        let template = Handlebars.compile(templateObj.html());
        let html = template(replyData);
        target.empty();
        target.append(html);
      }

      // 2) 댓글 페이징 출력작업
      // pageMaker : 페이징정보, target : 출력될 위치
      let printPaging = function(pageMaker, target){
        // <nav aria-label="Page navigation example">
        //   <ul class="pagination">
        //     <li class="page-item"><a class="page-link" href="#">Previous</a></li>
        //     <li class="page-item"><a class="page-link" href="#">1</a></li>
        //     <li class="page-item"><a class="page-link" href="#">Next</a></li>
        //   </ul>
        // </nav>
        let pagingStr = '<nav aria-label="Page navigation example">';
            pagingStr += '<ul class="pagination">';

          // 이전 표시 작업
          if(pageMaker.prev){
            pagingStr += '<li class="page-item"><a class="page-link" href="' + (pageMaker.startPage - 1);
            pagingStr += '">Previous</a></li>';
          }  

          // 페이지번호 표시작업
          for(let i=pageMaker.startPage; i<=pageMaker.endPage; i++){
            let strClass = (pageMaker.cri.pageNum == i) ? 'active' : ''; // 현재페이지 style
            pagingStr += '<li class="page-item ' + strClass + '"><a class="page-link" href="' + i + '">' + i + '</a></li>';
          }

          // 다음 표시 작업
          if(pageMaker.next) {
            pagingStr += '<li class="page-item"><a class="page-link" href="' + (pageMaker.endPage + 1);
            pagingStr += '">Next</a></li>';
          }

          pagingStr += '</ul>';
          pagingStr += '</nav>';

          // target 변수가 가리키는 위치에 pagingStr 변수의 내용을 삽입
          target.html(pagingStr);
      }

      //ajax구문으로 요청하는 작업.
      function getPage(url){
		    console.log(url);
        $.getJSON(url, function(data){

          //console.log(data);
          /*
            data.list : 댓글목록데이타, data.pageMaker : 댓글페이징정보
          */

          //댓글목록 출력기능 함수
          printData(data.list, $("#replyList"), $("#reply-template"));

          //댓글페이징출력기능 함수
          printPaging(data.pageMaker, $("#replyPaging"));

        });
      }


    </script>

2번 댓글작업에 해당 구문을 추가해서 댓글 페이징작업에 버튼작업을 활성화 시킨다

<script>
	  // 댓글 페이지번호 클릭. 동적인 태그를 이벤트 설정 할 경우에
      $("#replyPaging").on("click", "ul.pagination li a", function(e){
        e.preventDefault();

        // console.log("클릭");
        replyPage = $(this).attr("href"); // 1 2 3 4 5
        let url = "/replies/pages/" + bno + "/" + replyPage + ".json"; // 댓글목록및 페이징정보 요청주소

        getPage(url);

      });
</script>
<script>

// 댓글목록에서 수정버튼 클릭시
      $("#replyList").on("click", "input[name='btnModalModify']", function(){
        // console.log("클릭");

        // 현재 선택된 댓글 내용을 읽어와서, 모달대화상자에 보여준다
        let rno = $(this).parents("div.box-body").find("input[name='rno']").val();
        let replyer = $(this).parents("div.box-body").find("input[name='replyer']").val();
        let reply = $(this).parents("div.box-body").find("textarea[name='reply']").val();
        let replydate = $(this).parents("div.box-body").find("span").html();

        // console.log(rno);
        // console.log(replyer);
        // console.log(reply);
        // console.log(replydate);

        // Modal Dialog의 내용물 수정
        $("#replyTitle").html("Modify Reply");
        $("#rno").val(rno);
        $("#replyer").val(replyer);
        $("#reply").val(reply);
       
        $(".btnModal").hide(); // 모달대화상자의 3개버튼을 모두 보이지 않게
        $("#btn_replyModify").show();

        $("#replyModal").modal('show');
      });
    
</script>

댓글남기기