1. 댓글 수정 기능
1-1. 댓글 목록 조회
<div>
<div th:each="reply : ${reply}">
<div>[[${reply.replyWriter}]]</div>
<div>[[${reply.regDate}]]</div>
<div>[[${reply.replyContent}]]</div>
<div th:if="${session.loginInfo != null and session.loginInfo.memId == reply.replyWriter}">
<input type="button" value="수정"> <!-- 구현할 기능 -->
<input type="button" value="삭제" th:onclick="|location.href='@{/reply/deleteReply(replyNum=${reply.replyNum},boardNum=${board.boardNum})}'|">
</div>
</div>
</div>
controller에서 model 객체를 사용해 넘긴 댓글 목록을 받아 for-each문으로 댓글 목록 조회 기능을 구현했다.
각 댓글 하단에 수정, 삭제 버튼을 추가했고, 해당 버튼은 session에 로그인 정보가 저장되어 있고 로그인 아이디 정보가 댓글 작성자가 같을 때만 보여지도록 했다.
수정 버튼을 눌렀을 때 Javascript를 사용해 댓글 내용 div를 수정이 가능한 input 태그로 변경하려고 한다.
1-2. 댓글 수정 구현
<th:block layout:fragment="content_js">
<script type="text/javascript" src="/js/detail.js"></script>
</th:block>
자바스크립트 파일을 생성해 <script> 태그로 경로를 지정해줬다.
<input type="button" value="수정" th:onclick="setInput()">
버튼을 클릭하면 js 파일의 setInput 함수가 실행될 것이다.
1-2-1. 댓글 태그 내용 삭제
<input type="button" value="수정" th:onclick="setInput(this)">
댓글 내용이 담긴 태그를 찾아가기 위해서는 현재 태그를 나타내는 this를 함수의 매개변수로 지정해야 한다. id나 class로 태그를 지정하면 for문으로 인해 중복될 수 있기 때문에 현재 태그에서부터 찾아가는 방법을 써야 한다.
//댓글 수정 버튼 클릭 시 실행
function setInput(selectedTag) {
// 댓글 내용 태그 찾아가기
// 수정 버튼 태그의 부모 태그의 바로 이전 형제 태그
const contentDiv = selectedTag.parentElement.previousElementSibling;
// 댓글 원 내용 저장
const content = contentDiv.textContent;
// 선택한 태그 안의 내용 비우기
contentDiv.innerHTML = '';
}
this로 보낸 태그를 selectedTag로 받아 댓글 내용이 담긴 태그를 찾아간다. 댓글의 원래 내용을 input 태그에 담아줘야 하기 때문에 변수에 따로 저장한 후 내용을 비워준다.
1-2-2. 선택한 태그 안에 input 태그 넣기
//댓글 수정 버튼 클릭 시 실행
function setInput(selectedTag, replyNum, boardNum) {
// 댓글 내용 태그 찾아가기
const contentDiv = selectedTag.parentElement.previousElementSibling;
// 댓글 원 내용 저장
const content = contentDiv.textContent;
// 선택한 태그 안의 내용 비우기
contentDiv.innerHTML = '';
// 선택한 태그 안에 input 태그 넣기
const str = `<input type="text" value="${content}">`;
// 선택한 태그의 첫 번째 자식 태그로 삽입
contentDiv.insertAdjacentHTML('afterbegin', str);
//수정 버튼의 글자 변경
selectedTag.value = '확인';
}
value 값에 저장했던 내용을 담은 input 태그를 만들어 str 변수에 저장한다. 이때 백틱(``)으로 감싸 ${}안의 문자열이 이어지도록 한다. insertAdjacentHTML('추가할 위치', '추가할 태그')는 지정한 위치에 태그를 추가하는 기능이다. 선택한 태그의 첫 번째 자식 태그로 삽입한 후, 버튼의 글자를 '확인'으로 변경한다.
이때, 버튼의 글자가 '수정'일 경우와 '확인'일 경우 버튼의 기능이 달라야 하기 때문에 if문으로 구분하여 준다.
1-2-3. 댓글 수정 쿼리
<!-- 댓글 수정 -->
<update id="updateReply">
UPDATE SPRING_REPLY
SET
REPLY_CONTENT = #{replyContent}
WHERE REPLY_NUM = #{replyNum}
</update>
'확인' 버튼을 누르면 필요한 값을 가지고 controller로 가야 한다. 쿼리를 보면 필요한 값이 여러 개이기 때문에 input 태그를 form 태그로 감싸고 button 타입이 아닌 submit 타입으로 변경해준다.
1-2-4. form 태그 추가 및 submit 타입 변경
//댓글 수정 버튼 클릭 시 실행
function setInput(selectedTag, replyNum, boardNum) {
if(selectedTag.value == '수정') {
// 댓글 내용 태그 찾아가기
const contentDiv = selectedTag.parentElement.previousElementSibling;
// 댓글 원 내용 저장
const content = contentDiv.textContent;
// 선택한 태그 안의 내용 비우기
contentDiv.innerHTML = '';
// 선택한 태그 안에 input 태그 넣기
let str = ``;
str += '<form id="updateReplyForm" action="/reply/updateReply" method="post">';
str += `<input type="hidden" value="${boardNum}" name="boardNum">`;
str += `<input type="hidden" value="${replyNum}" name="replyNum">`;
str += `<input type="text" value="${content}" name="replyContent">`;
str += '</form>';
// 선택한 태그의 첫 번째 자식 태그로 삽입
contentDiv.insertAdjacentHTML('afterbegin', str);
//수정 버튼의 글자 변경
selectedTag.value = '확인';
}
else {
// form 태그 submit
document.querySelector('#updateReplyForm').submit();
}
}
수정 완료 후, 다시 해당 글 상세 페이지로 오기 위해서 필요한 boardNum을 hidden 속성의 input 태그로 보내준다.
선택한 태그의 value 값이 '수정'이 아닐 때는 form 태그를 submit 하는 기능을 하게 한다.
+) ReplyService
//댓글 수정
void updateReply(ReplyVO replyVO);
+) ReplyServiceImpl
// 댓글 수정
@Override
public void updateReply(ReplyVO replyVO) {
sqlSession.update("replyMapper.updateReply", replyVO);
}
+) ReplyController
// 댓글 수정
@PostMapping("/updateReply")
public String updateReply(ReplyVO replyVO) {
replyService.updateReply(replyVO);
return "redirect:/board/detail?boardNum=" + replyVO.getBoardNum();
}
post method의 form 태그에서 보냈기 때문에 PostMapping으로 받아 준다.
'TIL' 카테고리의 다른 글
| 220329 [Spring] (Interceptor) (0) | 2023.03.29 |
|---|---|
| 230322 [jQuery, Ajax] (데이터 주고받기) (0) | 2023.03.22 |
| 230320 [SQL, Spring] (페이징 처리) (0) | 2023.03.20 |
| 230317 [Spring, thymeleaf] (layout) (0) | 2023.03.17 |
| 230314 [Spring] (Model / 의존성 주입) (0) | 2023.03.14 |