본문 바로가기
웹개발/SpringBoot

댓글 수정, 삭제기능 추가하기 (API 호출, fetch)

by 철없는민물장어 2023. 3. 14.
728x90
수정기능
<div id="comments-list">
    {{#commentsDtos}}
        <div class="card m-2" id="comments-{{id}}">
            <div class="card-header">
                {{nickname}}
                <!-- Button trigger modal -->
                <button type="button" class="btn btn-sm btn-outline-primary"
                        data-bs-toggle="modal" data-bs-target="#comment-edit-modal"
                        data-bs-id="{{id}}"
                        data-bs-nickname="{{nickname}}"
                        data-bs-body="{{body}}"
                        data-bs-article-id="{{articleId}}">
                    edit
                </button>
                <button class="btn btn-sm btn-outline-danger" id="comment-delete-btn" data-id="{{id}}">delete</button>
            </div>
            <div class="card-body">
                {{body}}
            </div>
        </div>
    {{/commentsDtos}}
</div>

수정버튼을 누르면 모달창이 뜨도록,

모달 트리거 버튼을 추가해준다.

 

안에 data-bs가 무더기로 있는것은..

모달 트리거 버튼을 눌렀을 때 나오는 모달창으로

데이터를 전달하기 위함이다.


<!-- Modal -->
<div class="modal fade" id="comment-edit-modal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <form>
<!--                    닉네임 수정-->
                    <div class="mb-3">
                        <label class="form-label">nickname</label>
                        <input type="text" class="form-control form-control-sm" id="edit-comment-nickname">
                    </div>
<!--                    body 수정-->
                    <div class="mb-3">
                        <label class="form-label">comment</label>
                        <textarea type="text" class="form-control form-control-sm" rows="3" id="edit-comment-body"></textarea>
                    </div>
                    <!--히든 인풋-->
                    {{#article}}
                        <input type="hidden" id="edit-comment-id">
                        <input type="hidden" id="edit-comment-article-id">
                    {{/article}}

<!--                    버튼-->
                    <button type="button" class="btn btn-outline-primary btn-sm" id="comment-update-btn">save</button>
                </form>
            </div>

        </div>
    </div>
</div>

모달 코드도 추가해준다.

이 코드들은 부트스트랩에 있다..

 

let commentEditModal = document.querySelector("#comment-edit-modal");

    commentEditModal.addEventListener('show.bs.modal',function(event){
        //트리거 버튼 선택
        const triggerBtn = event.relatedTarget;

        //데이터 가져오기
        const id = triggerBtn.getAttribute('data-bs-id')
        const nickname = triggerBtn.getAttribute('data-bs-nickname')
        const body = triggerBtn.getAttribute('data-bs-body')
        const articleId = triggerBtn.getAttribute('data-bs-article-id')

        //데이터 반영하기
        document.querySelector("#edit-comment-nickname").value=nickname;
        document.querySelector("#edit-comment-body").value=body;
        document.querySelector("#edit-comment-id").value=id;
        document.querySelector("#edit-comment-article-id").value=articleId;
    })

여기서부터는 JS로 작성된 스크립트 태그 내부이다.

위 코드는 모달창이 열렸을 때, 수정 전 내용이 폼에 미리 입력되어있도록 하는 것이다.

모달 트리거버튼에 넣어두었던 데이터를 꺼내, 모달창 폼에 입력해둔다.

(article id, id는 히든인풋이라 보이지는 않지만, 나중에 update API 호출을 위해 입력함)

 

<!--수정버튼 눌러 API호출하기-->
{
    //수정 완료 버튼
    let commentUpdateBtn = document.querySelector("#comment-update-btn");

    commentUpdateBtn.addEventListener('click',function(){
        //수정댓글 객체 생성
        const comment = {
            id: document.querySelector("#edit-comment-id").value,
            nickname: document.querySelector("#edit-comment-nickname").value,
            body: document.querySelector("#edit-comment-body").value,
            article_id: document.querySelector("#edit-comment-article-id").value
        }

        //수정 restAPI 호출(fetch)
        const url = "/api/comments/" + comment.id;
        fetch(url,{
            method: "PATCH",
            body: JSON.stringify(comment),
            headers:{
                "Content-type":"application/json"
            }
        }).then((response)=>{
            //http응답코드에 따른 메세지 출력
            const msg = (response.ok) ? "edit fin":"edit error";
            alert(msg);
            //현재 페이지 새로고침
            window.location.reload();

        })
    })
}

1.수정을 위해, save버튼에 리스너를 부착.

2.폼에 입력된 값으로 JS 객체를 만듦.

3.fetch

3-1. body에는 JSON데이터가 들어가야하므로 JSON.stringify메소드를 이용하여 JS객체를 JSON으로 변환하여 사용

3-2. fetch완료 이후 수행할 작업을 .then으로 작성. 응답코드에 따라 메세지를 출력하고 페이지를 새로고침함.

 


삭제
<button class="btn btn-sm btn-outline-danger" id="comment-delete-btn" data-id="{{id}}">delete</button>

각 댓글에는 위와같은 삭제버튼을 추가.

이 때 data-id에 현재 댓글id를 넣어둔다.

(삭제 요청시에 댓글id가 필요하므로)

 

<!--댓글 삭제-->
{
    const commentDeleteBtns = document.querySelectorAll("#comment-delete-btn");

    commentDeleteBtns.forEach((commentDeleteBtn)=>{
        commentDeleteBtn.addEventListener('click',function(event){
            const target_id = event.target.dataset.id;

            //이렇게도 가능
            //const targetBtn = event.srcElement;
            //const commentId =targetBtn.getAttribute("data-id");
            const url = "/api/comments/"+target_id;
            fetch(url,{
                method:"DELETE"
            }).then((response)=>{
                //const msg = (response.ok) ? "deleted" : "delete error";
                //alert(msg);

                if(!response.ok){
                    alert("삭제실패");
                    return;
                }

                const target = document.querySelector(`#comments-${target_id}`)
                target.remove();
                //window.location.reload();
            })
        })
    })

}

이번엔 delete버튼이 여러개이므로

querySelectorAll메소드를 사용하여 모든 삭제버튼을 찾는다.

찾은 모든 버튼에 관해 addEventListener메소드 부착.

(forEach()메소드를 사용하면 모든 버튼에 리스너부착을 쉽게 할 수 있다)

 

삭제버튼 태그에 넣어두었던 data-id를 이용하여 삭제할 댓글의 id값을 가져오고,

fetch로 delete요청을 하면 된다.

 

삭제이후에는 삭제된 화면을 보여주기 위해 페이지를 새로고침해도 되지만

해당 삭제버튼이 있던 댓글을 감추기만 해도 된다.

728x90

댓글