본문 바로가기

BackEnd

querySelectAll로 리뷰 수정하기


각각의 리뷰별로 수정 삭제 버튼이 뜨게 만들기는 성공했다.
삭제는 reviewId 만 넘겨주면 됬기에 쉬웠는데

문제는.. 수정하기... 음 어렵다 어려워..
정렬된 순서의 index를 사용해서 그 review를 수정되도록 하려고 했는데

0번째 인덱스만 제대로 선택되고 나머지들은 알수없는 순서의 리뷰에 수정영역이 생성되는것을 확인했다.

  <div id="recent-reviews" th:if="${#lists.size(recentReviews) > 0}" >
    <div th:each="review, iterStat : ${recentReviews}" class="review-list">
      <div class="row-box">
        <h1 th:text="${review.id}"></h1>
        <input type="hidden" th:value="${review.id}" id="review-id"/>
        <input type="hidden" th:value="${review.isSpoiler()}" id="is-reviews-spoiler"/>
        <p th:text="${review.user.nickname}" class="review-writer">
<!--          <span th:if="${iterStat.index < 3}" class="best-icon">BEST</span> -->
        </p>
        <i class="fa-solid fa-ellipsis-vertical" th:id="'show-modal-' + ${iterStat.index}" th:if="${review.getUser().id} == ${userId}"></i>
        <div class="update-modal-container" th:id="'modal-container-' + ${iterStat.index}" th:if="${review.getUser().id} == ${userId}">
          <button class="update-review-btn" th:data-index="${iterStat.index}" th:data-review-id="${review.id}">수정</button>
          <hr />
          <button class="delete-review-btn" th:data-review-id="${review.id}">삭제</button>
        </div>
      </div>
      <p th:text="${review.content}" class="review-comment"></p>
      <div class="row-box">
        <span th:text="${#temporals.format(review.writeDate, 'yyyy-MM-dd HH:mm')}"></span>
        <div>
          <button id="recommend-like" class="recommend-btn" th:onclick="'javascript:likeReview(' + ${review.id} + ');'">
            <i class="fa-regular fa-thumbs-up"></i> <span th:text="${review.likeCount}"></span>
          </button>
          <button id="recommend-dislike" class="recommend-btn" th:onclick="'javascript:dislikeReview(' + ${review.id} + ');'">
            <i class="fa-regular fa-thumbs-down"></i> <span th:text="${review.dislikeCount}"></span>
          </button>
        </div>
      </div>
    </div>
  </div>
let reviewId = document.getElementById("review-id");

document.addEventListener("DOMContentLoaded", function() {
    function enableEditReview(index) {
        console.log( "생성된 텍스트 영역의 index = " + index)
        let reviewComment = document.querySelectorAll(".review-comment")[index];
        let currentContent = reviewComment.innerText;
        let textareaField = document.createElement("textarea");

        textareaField.value = currentContent;
        textareaField.className = "update-comment-textarea";

        reviewComment.replaceWith(textareaField);

        // Save 버튼 추가
        let saveButton = document.createElement("button");
        saveButton.innerText = "저장";
        saveButton.className = "save-review-btn";
        saveButton.onclick = function() {
            saveUpdatedReview(index);
        };

        textareaField.after(saveButton);
    }

    function saveUpdatedReview(index) {
        let textareaField = document.querySelectorAll(".update-comment-textarea")[index];
        console.log("saveUpdateReview의 index = " + index)
        if (!textareaField) {
            console.error('Textarea element not found.');
            return;
        }
        let updatedContent = textareaField.value;

        let reviewId = document.querySelectorAll(".update-review-btn")[index].dataset.reviewId;
        console.log("리뷰 id = " + reviewId)
        fetch(`/reviews/patch/${reviewId}`, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                content: updatedContent
            })
        })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Network response was not ok');
                }
                return response.json();
            })
            .then(data => {
                console.log('Review content updated successfully:', data);

                let reviewComment = document.createElement("p");
                reviewComment.className = "review-comment";
                reviewComment.innerText = updatedContent;

                textareaField.replaceWith(reviewComment);

                document.querySelectorAll(".save-review-btn")[index].remove();
            })
            .catch(error => {
                console.error('Error updating review content:', error);
            });
    }

    document.querySelectorAll(".update-review-btn").forEach(function(button, index) {
        button.addEventListener("click", function() {
            enableEditReview(index);
            console.log("선택된 리뷰 index = " + index)
        });
    });
});

 

코드를 바꿔가며 한시간정도 개발자도구에서 확인해보니 출력되는 index와 실제 조작되는 index가 달랐다.
뭔가..각각의 리뷰들을 구별할것을 추가해줘야할꺼같아서 고유한 식별자를 추가하였다.

<div id="recent-reviews" th:if="${#lists.size(recentReviews) > 0}">
    <div th:each="review, iterStat : ${recentReviews}" class="review-list" th:id="'review-' + ${review.id}">
        <div class="row-box">
            <h1 th:text="${review.id}"></h1>
            <input type="hidden" th:value="${review.id}" class="review-id"/>
            <input type="hidden" th:value="${review.isSpoiler()}" class="is-reviews-spoiler"/>
            <p th:text="${review.user.nickname}" class="review-writer"></p>
            <i class="fa-solid fa-ellipsis-vertical" th:id="'show-modal-' + ${iterStat.index}" th:if="${review.getUser().id} == ${userId}"></i>
            <div class="update-modal-container" th:id="'modal-container-' + ${iterStat.index}" th:if="${review.getUser().id} == ${userId}">
                <button class="update-review-btn" th:data-index="${iterStat.index}" th:data-review-id="${review.id}">수정</button>
                <hr />
                <button class="delete-review-btn" th:data-review-id="${review.id}">삭제</button>
            </div>
        </div>
        <p th:text="${review.content}" class="review-comment"></p>
        <div class="row-box">
            <span th:text="${#temporals.format(review.writeDate, 'yyyy-MM-dd HH:mm')}"></span>
            <div>
                <button id="recommend-like" class="recommend-btn" th:onclick="'javascript:likeReview(' + ${review.id} + ');'">
                    <i class="fa-regular fa-thumbs-up"></i> <span th:text="${review.likeCount}"></span>
                </button>
                <button id="recommend-dislike" class="recommend-btn" th:onclick="'javascript:dislikeReview(' + ${review.id} + ');'">
                    <i class="fa-regular fa-thumbs-down"></i> <span th:text="${review.dislikeCount}"></span>
                </button>
            </div>
        </div>
    </div>
</div>

 

자바스크립트에서도 해당 식별자를 찾도록 변경

document.addEventListener("DOMContentLoaded", function() {
    function enableEditReview(reviewId) {
        let reviewElement = document.querySelector("#review-" + reviewId);
        let reviewComment = reviewElement.querySelector(".review-comment");
        let currentContent = reviewComment.innerText;
        let textareaField = document.createElement("textarea");

        textareaField.value = currentContent;
        textareaField.className = "update-comment-textarea";

        reviewComment.replaceWith(textareaField);

        // Save 버튼 추가
        let saveButton = document.createElement("button");
        saveButton.innerText = "저장";
        saveButton.className = "save-review-btn";
        saveButton.onclick = function() {
            saveUpdatedReview(reviewId);
        };

        textareaField.after(saveButton);
    }

    function saveUpdatedReview(reviewId) {
        let reviewElement = document.querySelector("#review-" + reviewId);
        let textareaField = reviewElement.querySelector(".update-comment-textarea");

        if (!textareaField) {
            console.error('Textarea element not found.');
            return;
        }

        let updatedContent = textareaField.value;

        fetch(`/reviews/patch/${reviewId}`, {
            method: 'PATCH',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                content: updatedContent
            })
        })
        .then(response => {
            if (!response.ok) {
                throw new Error('Network response was not ok');
            }
            return response.json();
        })
        .then(data => {
            console.log('Review content updated successfully:', data);

            let reviewComment = document.createElement("p");
            reviewComment.className = "review-comment";
            reviewComment.innerText = updatedContent;

            textareaField.replaceWith(reviewComment);
            reviewElement.querySelector(".save-review-btn").remove();
        })
        .catch(error => {
            console.error('Error updating review content:', error);
        });
    }

    document.querySelectorAll(".update-review-btn").forEach(function(button) {
        button.addEventListener("click", function() {
            let reviewId = this.dataset.reviewId;
            enableEditReview(reviewId);
        });
    });
});

 

잘뜨는것을 확인헀다.