본문 바로가기

web +a

스프링부트 ~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이 반환하는 것은 버튼들의 묶음이다.

더보기

Document.querySelectorAll()

Document 메소드 querySelectorAll() 는 지정된 셀렉터 그룹에 일치하는 다큐먼트의 엘리먼트 리스트를 나타내는 정적(살아 있지 않은) NodeList 를 반환합니다.

 

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()라는 코드가 포함되어 있었다.

 

하지만 이번에는 삭제가 되면 바로 화면에서 지워준다. 새로고침 없이!

왜 이번에는 새로고침 없이 삭제가 되었을까?

수정도 그렇게 하면 안 되나? 

=> 된다. 자바스크립트로 잘 처리하면 된다.

 

아 다 되는구나! 정도만 알아두고 일단 넘어가자. 

곧 방법 공부해서 실제 플젝에 반영해바야지~

 

 

 


끝!!

 

꺄흑...

삭제 바로 반영되는거 보니까 신기하다. 

막 자바스크립트 공부하고 싶어지는..!!

곧 속성으로 그냥 슉 해버려야겠다.

반응형
다른 블로그