1. 개요.

  • 댓글 수정 페이지를 만들고 자바스크립트이벤트 처리를 통해 댓글을 수정.
    • 댓글 수정 페이지는 부트스트랩에서 제공하는 모달 기능을 이용해서 만듦.
      • 모달(modal)은 웹 페이지에 새 창을 띄우는 팝업 창과 달리 같은 웹 페이지 내부에서 상위 레이어를 띄우는 방식으로 사용하는 창.
      • 모달 창이 뜨면 기존 창은 비활성 상태가 되고, 모달 창을 닫아야만 원래 화면으로 돌아갈 수 있음.

  • 부트스트랩 -> Components -> Modal
    • 또는 Live demo 검색.
  • Launch demo modal 버튼을 클릭해보면 모달 창이 뜨는 것을 확인할 수 있음.


2. 뷰 페이지 만들기.

  • 댓글 목록을 담당하는 _list.mustache 파일의 코드를 수정.
    • 수정버튼은 닉네임 옆에 위치시킬거라 {{nickname}} 아래쪽에 <button>태그를 삽입.

2-1. 모달 트리거 버튼.

<div class="card-header">
    {{nickname}}
    <!-- Button trigger modal (댓글 수정 모달) -->
    <button type="button" class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#exampleModal">수정</button>
</div>
<div class="card-body">
    {{body}}
</div>
  • 수정 버튼 : 모달 트리거 버튼
    • 수정버튼을 클릭하면 모달이 실행.
  • data-bs-toggle="modal"
    • 클릭하면 모달이 나타나고 다시 클릭하면 사라짐. (토글 역할)
  • data-bs-target="#exampleModal"
    • 해당 id의 모달 실행.

2-2. 모달.

<!--  모달  -->
<div class="modal fade" id="exampleModal" 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">
                ...
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                <button type="button" class="btn btn-primary">Save changes</button>
            </div>
        </div>
    </div>
</div>
  • _list.mustache 제일 하단에 작성.

  • 수정버튼 클릭시 모달 창 생성되는 것을 확인.

<!--  모달(modal)  -->
<div class="modal fade" id="comment-edit-modal" tabindex="-1">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h1 class="modal-title" id="exampleModalLabel">댓글 수정</h1>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                댓글 모달 창 예시
            </div>
        </div>
    </div>
</div>
<!-- Button trigger modal (댓글 수정 모달 트리거 버튼) -->
<button type="button" class="btn btn-sm btn-outline-success" data-bs-toggle="modal" data-bs-target="#comment-edit-modal">수정</button>
  • 모달idcomment-edit-modal으로 수정.
    • 모달의 id를 수정했으니 모달 트리거 버튼data-bs-toggle 속성 도 같이 바꿔줌.
    • 이렇게 해야 버튼을 클릭했을 때 해당 모달 창이 뜸.


3. 수정 폼 삽입하기.

  • 모달 본문에 댓글 수정 삽입하기.
    • <form> 태그 사용.
    • 댓글 작성 뷰 페이지를 가져와서 사용.
<form>
    <!--  닉네임 입력  -->
    <div class="mb-3">
        <label class="form-label">닉네임</label>
        <input type="text" class="form-control" id="edit-comment-nickname">
    </div>
    <!--  댓글 본문 입력  -->
    <div class="mb-3">
        <label class="form-label">댓글 내용</label>
        <textarea type="text" class="form-control" rows="3" id="edit-comment-body"></textarea>
    </div>
    <!--  히든 인풋  -->
        <input type="hidden" id="edit-comment-id">
        <input type="hidden" id="edit-comment-article-id">
    <!--  전송 버튼  -->
    <button type="button" class="btn btn-primary" id="comment-update-btn">수정 완료</button>
</form>
  • 닉네임 input 박스의 id를 edit-comment-nickname으로 수정.
  • 댓글 본문 textarea 박스의 id를 edit-comment-body으로 수정.
  • 전송 버튼의 id를 comment-update-btn으로 수정.

  • 수정 버튼 클릭시 뜨는 모달 창.

4. 댓글 수정하기.

  • 수정 기존 댓글 데이터를 가져오고, 이를 자바스크립트 요청에 실어서 REST API호출한 후 처리.
    • 댓글을 수정하려면 무엇보다 기존 댓글 데이터를 가져와야 함.

_list.mustache

<div id="comments-list">
    <!--  댓글 목록  -->
    {{#commentDtos}}
        <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-success" data-bs-toggle="modal" data-bs-target="#comment-edit-modal">수정</button>
            </div>
            <div class="card-body">
                {{body}}
            </div>
        </div>
    {{/commentDtos}}
</div>
  • 위 코드를 보면 댓글{{#commentDtos}}...{{/commentDtos}} 머스테치 문법으로 감싸져 있음.
    • commentDtos에 저장된 commentDto의 수만큼 반복해서 댓글 데이터출력하라는 의미.
      • 해당 문법을 이용해서 commentDto에 저장된 데이터모달 트리거 버튼의 속성 으로 가져오기.
<button type="button" class="btn btn-sm btn-outline-success" 
	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}}">수정</button>
  • data-bs-*** 속성을 추가하고 현재 댓글의
    • {{id}}값을 저장.
    • {{nickname}}값을 저장.
    • {{body}}값을 저장.
    • {{articleId}}값을 저장.
  • data-로 시작하는 속성을 데이터 속성이라고 함.
    • 데이터 속성HTML 요소추가 정보를 저장하고 싶을 때 사용.
    • 개수에 제한이 없어서 하나의 요소여러 데이터 속성을 사용할 수 있음.
    • 속성 이름은 data-로 시작하고 그 다음은 마음대로 작성.

4-1. 모달 이벤트 처리.

_list.mustache

// 모달 이벤트 처리
<script>
    {
        
    }
</script>
  • 받아온 데이터모달의 각 에 출력.
    • 이를 모달 이벤트 처리라고 함.
<!--  모달 이벤트 처리  -->
<script>
    {   // 모달 요소 선택.
        const commentEditModal = document.querySelector("#comment-edit-modal");
        commentEditModal.addEventListener("show.bs.modal", function (event) {
            
        });
    }
</script>
  • const commentEditModal = document.querySelector("#comment-edit-modal");
    • querySelector()메서드로 모달을 선택하고 변수에 저장.
  • commentEditModal.addEventListener("show.bs.modal", function (event) {
    • 모달이 열리는 이벤트를 감지하고 있다가 이벤트가 발생하면 기존 댓글을 받아옴.
    • // 형식
      요소명.addEventListener("이벤트 타입", 이벤트 처리 함수)
    • show.bs.modal은 모달 동작의 이벤트 타입을 뜻함. (# 5번 참고)
    • function (event)
      • 모달이 열리는 이벤트매개변수로 받아 실행되는 함수.
        • 특정 이벤트 처리를 담당하는 함수를 이벤트 핸들러(event handler)라고 함.
    • "show.bs.modal", function (event)의 의미.
      • "show.bs.modal" : 모달이 열리기 직전 발생하는 이벤트.
      • function (event) : 이벤트 핸들러.
      • event : 발생된 이벤트 정보를 가리키는 매개변수. (show.bs.modal을 가리킴.)
        • 기본적으로 자바스크립트 이벤트 핸들러event 매개변수를 자동으로 전달함.
<!--  모달 이벤트 처리  -->
<script>
    {   // 모달 요소 선택.
        const commentEditModal = document.querySelector("#comment-edit-modal");
        // 모달 이벤트 감지.
        commentEditModal.addEventListener("show.bs.modal", function (event) {
            // 트리거 버튼 선택. (1)
            const triggerBtn = event.relatedTarget;
            
            // 데이터 가져오기. (2)
            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-articleId");
            
            // 수정 폼에 데이터 반영. (3)
            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;
        });
    }
</script>
  • 1번
    • 모달 트리거 버튼은 매개변수로 받은 event.relatedTarget으로 선택할 수 있음.
      • show.bs.modal 이벤트에서 event.target은 모달이 되고, event.relatedTarget은 트리거 버튼이 됨.
        • 이벤트의 주체가 모달이기 때문.
  • 2번
    • 앞서 모달 트리거 버튼의 속성값으로 댓글의 id, nickname, body, articleId를 저장했음.
    • triggerBtn.getAttribute()를 사용해서 각 변수에 저장.
      • 댓글의 id의 경우 data-bs-id속성에 저장했음.
  • 3번
    • 가져온 데이터를 모달의 각 폼에 반영함.
    • querySelector()를 사용해서 을 선택하고 해당 요소value 속성에 앞에서 가져온 을 저장.

  • 수정 버튼을 누르면 해당 댓글의 데이터가 사진처럼 불러와짐.

  • 개발자 도구에서 히든 인풋 값도 제대로 잘 나오는 모습.

4-2. REST API 호출, 응답.

  • 모달 창 정보로 댓글을 수정.
    • 수정 완료 버튼을 누르면 REST API를 호출.
// 모달 이벤트 처리
<script>
    {  
  				// 생략
    }
    {
        // 수정 완료 버튼 선택.
        const commentUpdateBtn = document.querySelector("#comment-update-btn");
        // 클릭 이벤트 처리
        commentUpdateBtn.addEventListener("click", function () {
           
        });
    }
</script>
  • querySelector()메서드를 사용해서 수정 완료 버튼(comment-update-btn)을 선택해서 변수에 저장.
  • addEventListener()로 수정 완료 버튼에 클릭 이벤트가 발생하면 함수(댓글 수정)가 실행.

4-2-1. 객체 생성.

  • 객체를 변수로 선언하는 객체 리터럴 방식으로 객체를 생성.
    • 객체의 키(key)id, nickname, body, articleId.
    • 각 키의 querySelector()로 댓글 수정 의 각 요소를 선택해서 value값을 가져옴.
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
    };
    console.log(comment);
});

  • 댓글을 수정하고 수정 완료를 버튼을 누른 후 관리자 도구를 보면 객체가 생성된 것을 확인할 수 있음.

4-2-2. fetch()함수.

commentUpdateBtn.addEventListener("click", function () {
    // 수정 댓글 객체 생성. (객체 리터럴 방식)
    const comment = {
				// 생략
      
    // 댓글 수정 REST API 호출.
    const url = "/api/comments/" + comment.id;	(1)
    fetch(url, {	(2)
        method: "PATCH"     // PATCH 요청.
        , headers: {        // 전송 데이터 타입 정보(JSON)
            "Content-Type": "application/json"
        },
        body: JSON.stringify(comment)       // comment 객체를 JSON 문자열로 변환해서 전송.
    }).then(response => {	(3)
        // HTTP 응답 코드에 따른 메시지 출력
        const msg = response.ok ? "댓글 수정 완료!" : "댓글 수정 실패...!"
        alert(msg);
        // 현재 페이지 새로고침.
        window.location.reload();
    });
});
  • 1번
    • 상수(const)타입의 url 변수에 댓글 수정 API 주소를 저장.
    • API주소에서 댓글의 id는 매번 변경되므로 comment.id(변수)로 처리.
  • 2번
    • 첫 번째 전달값으로 API 주소가 저장되어 있는 url을 넘김.
    • 두 번째 전달값으로 요청 메서드, 헤더 정보, 전송 본문을 넘김.
      • 헤더 정보에는 전송 본문 데이터의 타입이 JSON임을 명시하는 내용을 넣음.
      • 전송 데이터에는 comment 객체JSON 형태로 변환해서 전달하기 위해서 JSON.stringify() 메서드 사용.
  • 3번
    • responseAPI 요청을 보내고 받은 응답 객체.
    • msgalert()함수로 출력.


5. 모달 동작 이벤트 타입. (참고)

이벤트 타입설명
show.bs.modal- 모달이 표시되기 직전에 실행되는 이벤트.
shown.bs.modal- 모달이 표시된 후 실행되는 이벤트.
hide.bs.modal- 모달이 숨겨지기 직전에 실행되는 이벤트.
hidden.bs.modal- 모달이 숨겨진 후 실행되는 이벤트.
profile
Every cloud has a silver lining.

0개의 댓글