뷰 페이지를 만들고 자바스크립트의 이벤트 처리를 통해 댓글을 수정.모달 기능을 이용해서 만듦.모달(modal)은 웹 페이지에 새 창을 띄우는 팝업 창과 달리 같은 웹 페이지 내부에서 상위 레이어를 띄우는 방식으로 사용하는 창.비활성 상태가 되고, 모달 창을 닫아야만 원래 화면으로 돌아갈 수 있음.
부트스트랩 -> Components -> ModalLive demo 검색.Launch demo modal 버튼을 클릭해보면 모달 창이 뜨는 것을 확인할 수 있음.
_list.mustache 파일의 코드를 수정.수정버튼은 닉네임 옆에 위치시킬거라 {{nickname}} 아래쪽에 <button>태그를 삽입.<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의 모달 실행.<!-- 모달 -->
<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>
모달의 id를 comment-edit-modal으로 수정.모달 트리거 버튼의 data-bs-toggle 속성 값도 같이 바꿔줌.
폼 삽입하기.<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으로 수정.edit-comment-body으로 수정.comment-update-btn으로 수정.
수정 버튼 클릭시 뜨는 모달 창.폼에 기존 댓글 데이터를 가져오고, 이를 자바스크립트 요청에 실어서 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-로 시작하고 그 다음은 마음대로 작성._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)의 의미.※ 기본적으로 자바스크립트 이벤트 핸들러는 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번※ show.bs.modal 이벤트에서 event.target은 모달이 되고, event.relatedTarget은 트리거 버튼이 됨.2번triggerBtn.getAttribute()를 사용해서 각 변수에 저장.id의 경우 data-bs-id속성에 저장했음.3번querySelector()를 사용해서 폼을 선택하고 해당 요소의 value 속성에 앞에서 가져온 값을 저장.

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

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번API 주소를 저장.API주소에서 댓글의 id는 매번 변경되므로 comment.id(변수)로 처리.2번첫 번째 전달값으로 API 주소가 저장되어 있는 url을 넘김.두 번째 전달값으로 요청 메서드, 헤더 정보, 전송 본문을 넘김.객체를 JSON 형태로 변환해서 전달하기 위해서 JSON.stringify() 메서드 사용.3번response는 API 요청을 보내고 받은 응답 객체.msg를 alert()함수로 출력.


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