[ERROR, JAVASCRIPT] JSP (JSTL), JQuery로 댓글 삭제 구현시 작동 에러

JSP 파일에서 name, id, class 값 JQuery로 가져오기, Ajax 이용하기

Posted by iheese on July 19, 2022 · 7 mins read

에러 상황

commenterror

  • JPA를 이용한 게시판 댓글 삭제 기능 구현 중 에러가 발생했다.
  • 포스트 아래 댓글이 달리게 해놨고 댓글 작성자일 경우 삭제 버튼이 보이게 구현했다.
  • 근데 맨 위(1번) 위치에 있는 삭제 버튼만 작동했고 2번의 삭제 버튼을 누르면 아무 일도 일어나지 않았다. 1번 댓글 삭제하고 2번이 맨 위로 가면 2번만 삭제가 되었다.
  • view 파일은 jsp이고 부트스트랩을 이용했으며, jsp - Ajax(JavaScript, JQuery) - Controller - …로 연결되는 구현이었다.


수정 전 코드

.jsp 파일

<c:forEach var="reply" items="${replyList}">
	<tr>
	<td width="80%">${reply.content }</td>
	<td align="center">${reply.user.username}</td>
	<td align="center">
		<c:if test="${principal.getUsername() eq reply.user.username}">
		<form>
		<input type="hidden" id="id" value="${post.id}" />
    		<input type="hidden" id="seq" value="${reply.seq}" />
    		<button class="btn btn-secondary" id="btn-deleteReply" value ="${reply.seq}" >삭제</button>
		</form>
		</c:if>
	</td>
 	</tr>
</c:forEach>


Ajax.js 파일

let deleteReply = {
	init: function() {
		let _this = this;
		$("#btn-deleteReply").on("click", function() {
			_this.deleteReply();
		});
	},
	deleteReply: function(seq) {
		var id =  $("#id").val();
        var seq = $("#seq").val();
		$.ajax({
			type: "DELETE", 
			url: "/reply/"+seq
		}).done(function(response) {
			alert(response);
			location = "/posts/"+id;
		});
	}
}
deleteReply.init();


원인

  • form에 input 태그의 type = “hidden” 속성을 통해서 댓글의 id값(seq)를 담아 Ajax.js 파일을 통해 Controller에 보내 로직을 처리하려 했다.
  • 원인은 jsp 파일에서 id = “seq” 을 통해 js 파일에 접근하게 해서 그런 것이었다.


  • 주된 첫 번째 문제 : 태그 속성 중에서 name, class로 전달해주면 중복이 가능해서 <c:forEach> 에서 각각 값을 전달해줄 수 있는데 id는 중복을 허용하지 않기 때문에 첫 번째 버튼에만 값이 할당되었던 것이었다.
    • 부트스트랩을 사용하고 있기 때문에 class를 이용해서 값을 전달해줄 수는 없으니 name 속성을 이용해야 할 것 같다. (부트스트랩은 class 속성으로 css 처리를 한다.)
  • 주된 두 번째 문제 : 그렇다고 name, class를 통해 값을 전달하는 것은 안되었다. 왜냐하면 Ajax.js 파일에서 댓글의 id값에 얻기 위해 name, class에 접근해도 몇 번째 취소 버튼인지 몰라서 다른 버튼을 눌러도 맨 위의 댓글이 삭제되었다.


수정 후 코드

<c:forEach var="reply" items="${replyList}">
	<tr>
	<td width="80%">${reply.content }</td>
	<td align="center">${reply.user.username}</td>
	<td align="center">
		<c:if test="${principal.getUsername() eq reply.user.username}">
		<form>
			<input type="hidden" id="id" value="${post.id}" />
			<button class="btn btn-secondary" name="btn-deleteReply" value="${reply.seq}">삭제</button>
		</form> <!--변경부분-->
		</c:if>
   	</td>
	</tr>
</c:forEach>
  • input 태그의 type = “hidden” 을 통해 값을 전달하는 방법은 <c:forEach> 아래에서 큰 힘을 발휘하긴 어려운 것 같다. 모든 값이 같은 값을 가지게 되어 js 파일에서 구분하여 접근하는 것이 어려운 것 같다.
  • 그래서 button 태그 자체에 value 값을 주어 바로 접근하게 하였다.


Ajax.js파일

let deleteReply = {
	init: function() {
		let _this = this;
		$("button[name=btn-deleteReply]").on("click", function() {   		 //변경부분
			_this.deleteReply(this.value); //변경부분
		});
	},
	deleteReply: function(seq) {
		var id =  $("#id").val(); //화면 변경을 위한 post id
		$.ajax({ 
			type: "DELETE", 
			url: "/reply/"+seq
		}).done(function(response) {
			alert(response);
			location = "/posts/"+id;
		});
	}
}
deleteReply.init();
  • button이 클릭되면 해당 button의 value가 넘어가면서 댓글 삭제 Ajax가 호출된다.
  • this는 button을 의미하며 this.value를 통해 자기 자신의 값을 가져온다.

  • JQuery 값 불러오기
    • id : var a = $("#ID변수이름").val();
      • val(): value값을 의미
    • name : var b = $("button[name=NAME변수이름]")val();
      • button 위치에 태그명
      • var b = $("button[name=NAME변수이름]").eq("0").val(); : 첫 번째 값 가져온다.
    • class : var c = $(".CLASS변수이름").val();
      • var c = $(".CLASS변수이름").eq("1").val(); : 두 번째 값 가져온다.
        • name, class 모두 중복이 가능하여 인덱스로 접근 가능
    • '' (작은 따옴표)도 가능


마무리

  • 포스트 적고 보니 생각보다 간단한 문제였는데 꽤 오래 삽질했다.
  • 개인적으로 예외나 IDE에 에러가 뜨면 오히려 수정하기가 좋은 것 같은데, 작동은 하는데 내 마음대로 안될 때가 제일 어려운 것 같다.
    • 프론트 단(HTML, JS)에 대한 이해가 많이 부족한 것 같다.
  • Ajax를 이용하지 않고 <a href="/" class="btn">버튼</a> 를 이용하는 방법도 있을 것 같다. (다만 REST하지는 않은 방법이라 생각했다.)
  • input 태그의 type=”hidden”의 값에 구분하여 접근하는 방법이 있을 것 같은데 정말 모르겠다.
  • 배울 점이 많이 있으니 댓글로 부족한 점이나 더 좋은 방법을 알려주시면 좋을 것 같습니다.


Reference: