스프링부트 ~27 | 댓글 삭제 (+ JS)
intro
댓글 CRUD 구현의 마지막!!
댓글 삭제 기능도 지금까지 댓글 생성, 수정 요청을 js를 통해 구현한 것과 동일하다.
"삭제버튼 클릭 => js 통한 이벤트 처리로 rest api 요청"
시시시작~! >ㅅ<
전에 했던 거니까 간단히 슉슉쓰겠다.
먼저 삭제버튼 추가하고 시쟉하자
달린댓글 쭉 뜨는 해당 뷰페이지에다가 삭제버튼을 추가 슉슉
<button type="button"
class="btn btn-sm btn-outline-danger comment-delete-btn">삭제</button>
+ 버튼에 데이터 전달하기
구현하다보면 알게되지만,
click 이벤트 발생시 처리할 것은 '삭제'이고, 댓글을 삭제하려면 '댓글 id'가 필요함을 파악해야 했다.
recall) 버튼에 전달할 데이터는 버튼의 속성으로 넣어준다.
<button type="button"
class="btn btn-sm btn-outline-danger comment-delete-btn"
data-comment-id="{{id}}">삭제</button>
* 이제 이 데이터를 js로 가져올 수 있게 되었다!
그럼 본격적으로 삭제기능 구현 고고~!
● javascript 작성
javascript 작성 흐름은 다음과 같다. (전에 했던 것과 동일)
1. 버튼을 가져온다
recall) 버튼 컴포넌트 가져올 때 querySelector로 버튼을 가져왔던것을 기억!
cf) 이전에는 id로 가져왔다면 이번에는 class로 가져와보자.
cf) 원하는 동작 : 새로고침 없이 삭제삭제 처리
문제점 : 댓글 하나 삭제처리 후 다른댓글 삭제버튼을 누르면 이벤트가 안 먹힌다.
문제 이유 : querySelector는 제일 먼저 발견되는 버튼 하나만 반환한다.
새로고침 없이 여러 버튼에 대해 이벤트처리하고 싶다면 querySelectorAll을 사용해야 한다.
querySelectorAll이 반환하는 것은 버튼들의 묶음이다.
2. 그 버튼 '각각'에 대한 이벤트를 처리한다 : btns.forEach(btn => {...})과 같이 처리한다.
recall) btn.addEventListener("click", () => {...});
recall) function() {...} 랑 () => {...}랑 같은표현
<!-- 댓글 삭제 -->
<Script>
{
// 버튼 가져오고
const commentDeleteBtns = document.querySelectorAll(".comment-delete-btn");
// 버튼 이벤트 처리
commentDeleteBtns.forEach(btn => {
// 각 버튼의 이벤트 처리
btn.addEventListener("click", () => {
// 이벤트 처리 내용 작성
});
});
}
</script>
이벤트 처리는 어떻게 작성해야 할까?
버튼을 추가한 부분을 보자.
각 버튼에는 id 데이터를 전달했었다.
<button type="button"
class="btn btn-sm btn-outline-danger comment-delete-btn"
data-comment-id="{{id}}">삭제</button>
ⓐ 그럼 각 버튼에서 댓글 id 가져온 다음에
ⓑ 삭제 api 호출하는 내용을 슉 작성하면 되겠네..
↓ 각 버튼에서 id 가져오는 처리
<Script>
{
const commentDeleteBtns = document.querySelectorAll(".comment-delete-btn");
commentDeleteBtns.forEach(btn => {
btn.addEventListener("click", (event) => {
// event를 발생시킨 컴포넌트를 선택한다 (즉 버튼)
const commentDeleteBtn = event.target;
// 그 버튼에서 삭제 댓글 id를 가져온다.
const commentId = commentDeleteBtn.getAttribute("data-comment-id");
console.log(`삭제 버튼 클릭: ${commentId}번 댓글`); // cf) JS 백틱 문자열
});
});
}
</script>
※ evnet매개변수
click event가 발생했을 때, 그 event와 관련된 버튼을 가져와야 한다.
∴ event를 매개변수로 넣어줘야 한다.
cf) 백틱할때 작은따옴표 '가 아니라 키보드 물결표에 있는 `이거다
● 삭제 api 호출 & 처리
recall) api는 fetch()를 통해서 호출했다!
fetch(url, {보낼내용}).then(response => {응답후행동}) : rest api 호출
↓ 요 내용을 클릭이벤트 처리 로직에 넣으면 되는거죠~!!
// 삭제 API 호출 및 처리
const url = `/api/comments/${commentId}`; // cf. js 백틱
fetch(url, {
method: "DELETE" // http의 DELETE메서드로 fetch할 거다! 명시
}).then(response => {
// 댓글 삭제 실패 처리
if (!response.ok) {
alert("댓글 삭제 실패");
return;
}
// 삭제 성공시 댓글을 화면에서 지움
const target = document.querySelector(`#comments-${commentId}`);
target.remove();
});
recall) 위 삭제 url은 댓글컨트롤러에서 @DeleteMapping으로 삭제메서드와 연결되었던 것 기억!
cf) 댓글은 부트스트랩의 card형태로 넣었다. 댓글 자체를 통으로 가져오기 위해 그 card 컴포넌트 id를 가져오면 된다. card의 id는 comments-{{id}}로 정했었다.
cf) 그 댓글(target) 가져와서 target.remove()하면 새로고침 안해도 댓글이 뿅 사라진다.
왜 이번에는 새로고침 없이 삭제한게 뷰에 반영이 되었나?
이전에 수정이벤트 처리 로직에서는 수정된 데이터를 화면에 표시하기 위해 '새로고침'했다.
∴ window.location.reload()라는 코드가 포함되어 있었다.
하지만 이번에는 삭제가 되면 바로 화면에서 지워준다. 새로고침 없이!
왜 이번에는 새로고침 없이 삭제가 되었을까?
수정도 그렇게 하면 안 되나?
=> 된다. 자바스크립트로 잘 처리하면 된다.
아 다 되는구나! 정도만 알아두고 일단 넘어가자.
곧 방법 공부해서 실제 플젝에 반영해바야지~
끝!!
꺄흑...
삭제 바로 반영되는거 보니까 신기하다.
막 자바스크립트 공부하고 싶어지는..!!
곧 속성으로 그냥 슉 해버려야겠다.