국비지원/리액트

스프링 백엔드 - 프로젝트 생성 후 postman으로 테스트, 대댓글 작성법 설명

compass195 2024. 11. 14. 14:38

리액트 첫 시간
대댓글, 컨트롤러와 

 

 

 

 

 

 

대댓글은 entity 부분만 잘 이해하고 만들면 어렵지 않음
2시 115분 녹화 영상 보기  comments1/src/main/resources/templates/board/view.html at master · sifter0926/comments1
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6"
      layout:decorate="~{layout/basic.html}">

<div layout:fragment="content">
    <div class="container mt-3">
        <h3>Board View</h3>
        <br />
        <div class="form-group">
          <label for="num">글번호:</label>
          <input type="text" class="form-control" id="num" name="num" th:value="${board.num}" readonly="readonly">
        </div>
        <div class="form-group">
          <label for="title">제목:</label>
          <input type="text" class="form-control" id="title" name="title" th:value="${board.title}" readonly="readonly">
        </div>
        <div class="form-group">
          <label for="writer">글쓴이:</label>
          <input type="text" class="form-control" id="writer" name="writer" th:value="${board.writer}" readonly="readonly">
        </div>
        <div class="form-group">
          <label for="content">내용:</label>
          <textarea name="content" id="content" class="form-control" readonly="readonly">[[${board.content }]]</textarea>
        </div>
        <div class="form-group">
           <label for="regDate">등록일:</label>
           <input type="text" class="form-control" id="regDate" name="regdate" th:value="${board.regdate}" readonly="readonly">
        </div>
        <div class="form-group">
           <label for="writer">조회수:</label>
           <input type="text" class="form-control" id="hitcount" name="hitcount" th:value="${board.hitcount}" readonly="readonly">
        </div>
        <div class="form-group">
           <label for="replycount">댓글 수:</label>
           <input type="text" class="form-control" id="replycount" name="replycount" th:value="${board.replycount}" readonly="readonly">
        </div>
        <div class="form-group mt-5">

          <span sec:authorize="isAuthenticated()" th:if="${#authentication.principal.username==board.getWriter()}">
            <a th:href="|@{/board/modify(num=${board.num})}|">
                <button type="button" id="btnUpdate" class="btn btn-secondary">수정</button>
            </a>
            <a th:href="|@{/board/delete(num=${board.num})}|">
                <button type="button" id="btnDelete" class="btn btn-danger">삭제</button>
            </a>
          </span>
           <a th:href="|@{/board/list}|">
              <button type="button" id="btnList" class="btn btn-info">List</button>
          </a>
        </div>
    </div>

    <!--    댓글 영역-->
    <div class="row mt-3">
        <div class="col-md-12">
            <div class="my-4 ">
                <button sec:authorize="isAuthenticated()" class="btn btn-info  addCommentBtn">ADD Comment</button>
            </div>
            <ul class="list-group commentList">  //여기에 댓글 리스트가 나옴. 그래서 ul 적어두신 것
                댓글 리스트 영역
            </ul>
        </div>
    </div>
    <div class="row mt-3">
        <div class="col">
            <ul class="pagination commentPaging">
            </ul>
        </div>
    </div>

    <div class="modal registerModal" tabindex="-1">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Register Replyer</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div class="input-group mb-3">
                        <span class="input-group-text">Reply Text</span>
                        <input type="text" class="form-control replyText" >
                    </div>
                    <div class="input-group mb-3">
                        <span class="input-group-text">Replyer</span>
                        <input type="text" class="form-control replyer" >
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-primary registerBtn">Register</button>
                    <button type="button" class="btn btn-outline-dark closeRegisterBtn" >Close</button>
                </div>
            </div>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="/js/comment.js"></script>

</div>

<script layout:fragment="script" th:inline="javascript">     //이 부분이 꼭 필요함 
    const board_id=[[${board.num}]]

    const commentList = document.querySelector('.commentList') //댓글 목록 DOM
    let str =''
    function printList(dtoList){ //댓글 목록 출력      //DTO리스트가 옴

        //console.log(dtoList)

        if(dtoList && dtoList.length > 0){

            for (const dto of dtoList) {   //dto 리스트에 있는 것을 가져옴

                 str += `<li class="list-group-item d-flex commentItem">
                       <span class="col-1">${dto.id}</span>
                        <span class="col-6" data-rno="${dto.id}">${dto.content}</span>
                        <span class="col-2">${dto.writer}</span>
                        <span class="col-2">${dto.regdate} </span>

                        <button class="btn btn-outline-dark addReplyBtn" data-cno="${dto.id}">댓글작성</button>   //대댓글을 넣기 위한 버튼

                     </li>`
                 if(dto.children && dto.children.length >0){     //재귀호출  현재 나는 printlist임 chilren이 없을 때까지 돌면서 뿌리는 원리
                     str+=' <ul>'
                     printList(dto.children)
                     str+=' </ul>'
                 }
            }

        }
        commentList.innerHTML = str;   //str 만든 것을 뿌려줌  (str은 115열부터 123열까지 끝나고, 만약 대댓글이 있으면 또 이걸 돌면서 화면에 뿌려줌
    }
    function printComments(){   //이걸 그대로 뿌리면 같은 것이 여러번 뿌려짐. 그래서 새로 댓글을 추가하면 또 list를 가져오게 되므로 printComments에서 다시 초기화를 함
        str=''
       commentList.clear  //초기화
        getList(board_id).then(    // getList는 axios로 연결한 것을 만들어 둔 곳에서 가져옴
            data => {

                //console.log((data))
                printList(data) //목록 처리   //뿌림
                //printPages(data) //페이지 처리
            }
        ).catch(e => {
            console.error(e)
        })
    }
    printComments();   //페이지가 열리자마자 printComments 호출해서 화면에 뿌리는 역할 -> 데이터 가져옴 -> printlist로 가서 뿌림

    const registerModal = new bootstrap.Modal(document.querySelector(".registerModal"))
    //registerModel
    const registerBtn = document.querySelector(".registerBtn")
    const replyText = document.querySelector(".replyText")
    const replyer = document.querySelector(".replyer")
    const closeRegisterBtn = document.querySelector(".closeRegisterBtn")
    let parentId=''  // parentId는 값이 바뀌므로 let으로 선언함 
    document.querySelector(".addCommentBtn").addEventListener("click", function (e){
        //replyer.value=writer  
        registerModal.show()   //모달을 띄움
    },false)

    closeRegisterBtn.addEventListener("click", function (e){
        registerModal.hide()
    },false)

    registerBtn.addEventListener("click", function(e){
        let commentObj=null
        if(parentId=='') {   // parentId가 공백
            commentObj = {
                content: replyText.value,
                writer: replyer.value,
            }
        }else{
            commentObj = {
                content: replyText.value,
                writer: replyer.value,
                parentId : parentId
            }
        }

        addComment(commentObj, board_id).then(result => {  //comment.js에 이 부분 만든 부분 있음
            alert(result)   //이부분이 결과가 나오는 것임
            registerModal.hide() //add누른 후에 모달 닫고, 값 지워서 새로 뿌릴 수 있게 준비
            replyText.value = ''
            replyer.value =''
            printComments() //댓글 목록 갱신
        }).catch(e => {
            alert("Exception...")
        })
    }, false)

    //대댓글 추가 영역
    //const replyModal = new bootstrap.Modal(document.querySelector(".replyModal"))
    //registerModel

    const addReplyBtn=document.querySelector(".commentList")

    addReplyBtn.addEventListener("click", function (e){

        parentId=e.target.getAttribute("data-cno")
        registerModal.show()

    },false)

</script>
</html>


 

 

 

async function getList(bno) {

    const result = await axios.get(`/comments/${bno}`)   //axios와 연결함
    console.log(result.data) //이런식으로 테스트하면서 하기
    return result.data;  //result에서 data 즉, 댓글 리스트를 가져옴
}

// async function getList({bno, page, size, goLast}){
//
//     const result = await axios.get(`/comments/${bno}`, {params: {page, size}})
//
//     if(goLast){
//         const total = result.data.total
//         const lastPage = parseInt(Math.ceil(total/size))
//         return getList({bno:bno, page:lastPage, size:size})
//     }
//
//     return result.data
// }

async function addComment(commentObj, boardId) {
    const response = await axios.post(`/comments/${boardId}`,commentObj)
    return response.data
}

async function addReComment(commentObj, parentId) {
    const response = await axios.post(`/comments/${parentId}`,commentObj)
    return response.data
}

async function getComment(id) {
    const response = await axios.get(`/comments/${id}`)
    return response.data
}

async function modifyComment(commentObj) {

    const response = await axios.put(`/comments/${commentObj.id}`, replyObj)
    return response.data
}

async function removeComment(id) {
    const response = await axios.delete(`/comments/${id}`)
    return response.data
}

comments1/src/main/resources/static/js/comment.js at master · sifter0926/comments1

 

comments1/src/main/resources/static/js/comment.js at master · sifter0926/comments1

Contribute to sifter0926/comments1 development by creating an account on GitHub.

github.com

 

 

comments1/src/main/resources/templates/board/view.html at master · sifter0926/comments1

 

comments1/src/main/resources/templates/board/view.html at master · sifter0926/comments1

Contribute to sifter0926/comments1 development by creating an account on GitHub.

github.com

여기서 위의 자바스크립트 함수를 호출함 printComments 함수를 호출함

 

 

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6"
      layout:decorate="~{layout/basic.html}">

<div layout:fragment="content">
    <div class="container mt-3">
        <h3>Board View</h3>
        <br />
        <div class="form-group">
          <label for="num">글번호:</label>
          <input type="text" class="form-control" id="num" name="num" th:value="${board.num}" readonly="readonly">
        </div>
        <div class="form-group">
          <label for="title">제목:</label>
          <input type="text" class="form-control" id="title" name="title" th:value="${board.title}" readonly="readonly">
        </div>
        <div class="form-group">
          <label for="writer">글쓴이:</label>
          <input type="text" class="form-control" id="writer" name="writer" th:value="${board.writer}" readonly="readonly">
        </div>
        <div class="form-group">
          <label for="content">내용:</label>
          <textarea name="content" id="content" class="form-control" readonly="readonly">[[${board.content }]]</textarea>
        </div>
        <div class="form-group">
           <label for="regDate">등록일:</label>
           <input type="text" class="form-control" id="regDate" name="regdate" th:value="${board.regdate}" readonly="readonly">
        </div>
        <div class="form-group">
           <label for="writer">조회수:</label>
           <input type="text" class="form-control" id="hitcount" name="hitcount" th:value="${board.hitcount}" readonly="readonly">
        </div>
        <div class="form-group">
           <label for="replycount">댓글 수:</label>
           <input type="text" class="form-control" id="replycount" name="replycount" th:value="${board.replycount}" readonly="readonly">
        </div>
        <div class="form-group mt-5">

          <span sec:authorize="isAuthenticated()" th:if="${#authentication.principal.username==board.getWriter()}">
            <a th:href="|@{/board/modify(num=${board.num})}|">
                <button type="button" id="btnUpdate" class="btn btn-secondary">수정</button>
            </a>
            <a th:href="|@{/board/delete(num=${board.num})}|">
                <button type="button" id="btnDelete" class="btn btn-danger">삭제</button>
            </a>
          </span>
           <a th:href="|@{/board/list}|">
              <button type="button" id="btnList" class="btn btn-info">List</button>
          </a>
        </div>
    </div>

    <!--    댓글 영역-->
    <div class="row mt-3">
        <div class="col-md-12">
            <div class="my-4 ">
                <button sec:authorize="isAuthenticated()" class="btn btn-info  addCommentBtn">ADD Comment</button>
            </div>
            <ul class="list-group commentList">
                댓글 리스트 영역
            </ul>
        </div>
    </div>
    <div class="row mt-3">
        <div class="col">
            <ul class="pagination commentPaging">
            </ul>
        </div>
    </div>

    <div class="modal registerModal" tabindex="-1">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Register Replyer</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <div class="input-group mb-3">
                        <span class="input-group-text">Reply Text</span>
                        <input type="text" class="form-control replyText" >
                    </div>
                    <div class="input-group mb-3">
                        <span class="input-group-text">Replyer</span>
                        <input type="text" class="form-control replyer" >
                    </div>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-primary registerBtn">Register</button>
                    <button type="button" class="btn btn-outline-dark closeRegisterBtn" >Close</button>
                </div>
            </div>
        </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script src="/js/comment.js"></script>

</div>

<script layout:fragment="script" th:inline="javascript">
    const board_id=[[${board.num}]]

    const commentList = document.querySelector('.commentList') //댓글 목록 DOM
    let str =''
    function printList(dtoList){ //댓글 목록 출력

        //console.log(dtoList)

        if(dtoList && dtoList.length > 0){

            for (const dto of dtoList) {

                 str += `<li class="list-group-item d-flex commentItem">
                       <span class="col-1">${dto.id}</span>
                        <span class="col-6" data-rno="${dto.id}">${dto.content}</span>
                        <span class="col-2">${dto.writer}</span>
                        <span class="col-2">${dto.regdate} </span>

                        <button class="btn btn-outline-dark addReplyBtn" data-cno="${dto.id}">댓글작성</button>
//현재 댓글의 아이디를 가져와서 대댓글을 쓸 수 잇음...?? 2시 36분 영상 다시 보기

                     </li>`
                 if(dto.children && dto.children.length >0){
                     str+=' <ul>'
                     printList(dto.children)
                     str+=' </ul>'
                 }
            }

        }
        commentList.innerHTML = str;
    }
    function printComments(){
        str=''
       commentList.clear
        getList(board_id).then(
            data => {

                //console.log((data))
                printList(data) //목록 처리
                //printPages(data) //페이지 처리
            }
        ).catch(e => {
            console.error(e)
        })
    }
    printComments();

    const registerModal = new bootstrap.Modal(document.querySelector(".registerModal"))
    //registerModel
    const registerBtn = document.querySelector(".registerBtn")
    const replyText = document.querySelector(".replyText")
    const replyer = document.querySelector(".replyer")
    const closeRegisterBtn = document.querySelector(".closeRegisterBtn")
    let parentId=''
    document.querySelector(".addCommentBtn").addEventListener("click", function (e){
        //replyer.value=writer
        registerModal.show()
    },false)

    closeRegisterBtn.addEventListener("click", function (e){
        registerModal.hide()
    },false)

    registerBtn.addEventListener("click", function(e){
        let commentObj=null
        if(parentId=='') {
            commentObj = {
                content: replyText.value,
                writer: replyer.value,
            }
        }else{
            commentObj = {
                content: replyText.value,
                writer: replyer.value,
                parentId : parentId
            }
        }

        addComment(commentObj, board_id).then(result => {
            alert(result)
            registerModal.hide()
            replyText.value = ''
            replyer.value =''
            printComments() //댓글 목록 갱신
        }).catch(e => {
            alert("Exception...")
        })
    }, false)

    //대댓글 추가 영역
    //const replyModal = new bootstrap.Modal(document.querySelector(".replyModal"))
    //registerModel

    const addReplyBtn=document.querySelector(".commentList")

    addReplyBtn.addEventListener("click", function (e){

        parentId=e.target.getAttribute("data-cno")
        registerModal.show()

    },false)

</script>
</html>