커뮤니티 - 댓글 수정 기능 구현 (23.07.21,24)

·2023년 7월 21일
1

Server

목록 보기
28/35
post-thumbnail

📝 댓글 수정 기능


💡 VS Code

🔎 reply.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<div id="reply-area">
    <!-- 댓글 목록 -->
    <div class="reply-list-area">

        <ul id="reply-list">

            <c:forEach var="reply" items="${rList}">

                <li class="reply-row">

                    <p class="reply-writer">
                        <c:if test="empty reply.profileImage">
                            <!-- 프로필 이미지가 없을 경우 -->
                            <img src="${contextPath}/resources/images/user.png">
                        </c:if>

                        <c:if test="!empty reply.profileImage">
                            <!-- 프로필 이미지가 없을 경우 -->
                            <img src="${contextPath}${reply.profileImage}">
                        </c:if>

                        <span>${reply.memberNickname}</span>
                        <span class="reply-date"> ${reply.createDate} </span>
                    </p>
                        
                    <p class="reply-content">${reply.replyContent}</p>
    
                    <c:if test="${loginMember.memberNo == reply.memberNo}">
                        <div class="reply-btn-area">
                            <button onclick="showUpdateReply(${reply.replyNo}, this)">수정</button>
                            <button onclick="deleteReply(${reply.replyNo})">삭제</button>
                        </div>
                    </c:if>

                </li>

            </c:forEach>

        </ul>

    </div>

    <!-- 댓글 작성 부분 -->

    <div class="reply-write-area">
        <textarea id="replyContent"></textarea>
        <button id="addReply">
            댓글<br>
            등록
        </button>
    </div>

</div>

🔎 reply.js

// 댓글 수정 화면 전환

let beforeReplyRow; // 수정 전 원래 행의 상태를 저장할 변수

function showUpdateReply(replyNo, btn){
                    // 댓글번호, 이벤트발생요소(수정버튼)

    // ** 댓글 수정이 한 개만 열릴 수 있도록 만들기 **
    const temp = document.getElementsByClassName("update-textarea");

    if(temp.length > 0){ //  수정이 한 개 이상 열려 있는 경우

        if(confirm("다른 댓글이 수정 중입니다. 현재 댓글을 수정 하시겠습니까?")){ // 확인

            temp[0].parentElement.innerHTML = beforeReplyRow;
            // reply-row                      // 백업한 댓글
            // 백업 내용으로 덮어 씌워 지면서 textarea 사라짐

        } else{ // 취소
           return;
        }

    }

    // 1. 댓글 수정이 클릭된 행을 선택
    const replyRow = btn.parentElement.parentElement // 수정 버튼의 부모의 부모

    // 2. 행 내용 삭제 전 현재 상태를 저장(백업) (문자열)
    //  (전역변수 이용)
    beforeReplyRow = replyRow.innerHTML;

    // 취소 버튼 동작 코드
    //replyRow.innerHTML = beforeReplyRow;

    // 3. 댓글에 작성되어 있던 내용만 얻어오기 -> 새롭게 생성된 textarea 추가될 예정

    // console.log(replyRow.children[1].innerHTML); // <br> 태그 유지를 위해서 innerHTML 사용
    let beforeContent = replyRow.children[1].innerHTML;

    // 이것도 가능
    //let beforeContent = btn.parentElement.previousElementSibling.innerHTML;
    
    // 4. 댓글 행 내부 내용을 모두 삭제
    replyRow.innerHTML = "";
    
    // 5. textarea 요소 생성 + 클래스 추가 + **내용 추가**
    const textarea = document.createElement("textarea");
    textarea.classList.add("update-textarea");

    
    // *************************************************
    // XSS 방지 처리 해제
    beforeContent = beforeContent.replaceAll("&amp;", "&");
    beforeContent = beforeContent.replaceAll("&lt;", "<");
    beforeContent = beforeContent.replaceAll("&gt;", ">");
    beforeContent = beforeContent.replaceAll("&quot;", "\"");

    // 개행문자 처리 해제
    beforeContent = beforeContent.replaceAll("<br>", "\n");

    // *************************************************
    
    
    textarea.value = beforeContent; // 내용 추가

    // 6. replyRow에 생성된 textarea 추가
    replyRow.append(textarea);

    // 7. 버튼 영역 + 수정/취소 버튼 생성
    const replyBtnArea = document.createElement("div");
    replyBtnArea.classList.add("reply-btn-area");

    const updateBtn = document.createElement("button");
    updateBtn.innerText = "수정";
    updateBtn.setAttribute("onclick", "updateReply(" +replyNo+ ", this)");

    const cancelBtn = document.createElement("button");
    cancelBtn.innerText = "취소";
    cancelBtn.setAttribute("onclick", "updateCancel(this)");

    // 8. 버튼영역에 버튼 추가 후
    //    replyRow(행)에 버튼영역 추가
    replyBtnArea.append(updateBtn, cancelBtn);
    replyRow.append(replyBtnArea);

}

// --------------------------------------------------------------------------------------
// 댓글 수정 취소
function updateCancel(btn){
    // 매개변수 btn : 클릭된 취소 버튼
    // 전역변수 beforeReplyRow : 수정 전 원래 행(댓글)을 저장한 변수
    
    if(confirm("댓글 수정을 취소하시겠습니까?")){
        btn.parentElement.parentElement.innerHTML = beforeReplyRow;
    }

}

// ---------------------------------------------------------------------------------------
// 댓글 수정(AJAX)
function updateReply(replyNo, btn){

    // 새로 작성된 댓글 내용 얻어오기
    const replyContent = btn.parentElement.previousElementSibling.value;

    $.ajax({
        url : contextPath + "/reply/update",
        data : {"replyNo" : replyNo,
                "replyContent" : replyContent},
        type : "POST",
        success : function(result){
            if(result > 0){
                alert("댓글이 수정되었습니다.");
                selectReplyList();

            }else{
                alert("댓글 수정 실패");
            }
        },
        error : function(req, status, error){
            console.log("댓글 수정 실패");
            console.log(req.responseText);
        }        

    });
}

💡 Eclipse

🔎 ReplyController.java

...
			// 댓글 수정
			if(command.equals("update")) {
				
				int replyNo = Integer.parseInt( req.getParameter("replyNo") );
				String replyContent = req.getParameter("replyContent");
				
				int result = service.updateReply(replyNo, replyContent);
				
				resp.getWriter().print(result);
			}
...

🔎 ReplyService.java

...
	/** 댓글 수정 Service
	 * @param replyNo
	 * @param replyContent
	 * @return result
	 * @throws Exception
	 */
	public int updateReply(int replyNo, String replyContent) throws Exception{
		
		Connection conn = getConnection();
		
		// XSS 처리
		replyContent = Util.XSSHandling(replyContent);
		
		// 개행문자 처리
		replyContent = Util.newLineHandling(replyContent);
		
		int result = dao.updateReply(conn, replyNo, replyContent);
		
		if(result > 0) commit(conn);
		else		   rollback(conn);
		
		close(conn);
		
		return result;
	}

🔎 ReplyDAO.java

	/** 댓글 수정 DAO
	 * @param conn
	 * @param replyNo
	 * @param replyContent
	 * @return result
	 * @throws Exception
	 */
	public int updateReply(Connection conn, int replyNo, String replyContent) throws Exception {
		
		int result = 0;
		
		try {
			String sql = prop.getProperty("updateReply");
			
			pstmt = conn.prepareStatement(sql);
			
			pstmt.setString(1, replyContent);
			pstmt.setInt(2, replyNo);
			
			result = pstmt.executeUpdate();
			
		} finally {
			close(pstmt);
		}
		
		return result;
	}

🔎 reply-sql.xml

	<!-- 댓글 수정 -->
	<entry key="updateReply">
		UPDATE REPLY SET
		REPLY_CONTENT = ?
		WHERE REPLY_NO = ?
	</entry>

profile
풀스택 개발자 기록집 📁

1개의 댓글

comment-user-thumbnail
2023년 7월 21일

정리를 잘해놓으셨네요..!

답글 달기