댓글정렬  @OrderBy

최근에 적은 댓글이 맨앞으로 보이게 정렬하도록 한다. = 내림차순

 

[Board]

@OneToMany(mappedBy = "board",fetch = FetchType.EAGER) /
@JsonIgnoreProperties({"board"})
@OrderBy("id  decs")   // 내림차순 정렬
private List<Reply> replys;

 

 

 

 

 

댓글 작성

댓글쓰기는 ajax 를 통해 비동기 처리 

 

1. 

[detail.jsp]

<!-- 게시글 댓글  -->

<div class="card">
    <form action="">
        <input type="hidden" id="boardId" value="${board.id}" >
        <div class="card-body">
            <textarea id="reply-content" class="form-control" rows="1" ></textarea>
        </div>
        <div class="card-footer">
            <button type="button" id="btn-rely-save" class="btn btn-primary">등록</button>
        </div>
    </form>
</div>
.
.
.
<script src="/js/board.js"></script>

 

- 어떤 게시글인지 알기 위해서는 board.id를 히든값으로 넣는다. 

  • <input type="hidden" id="boardId" value="${board.id}" > 

 

- 등록 버튼을 눌렀을때 textarea를 들고 자바스크립트로 이동. 

 

 

* 버튼태그에 type="button" 을 안적어주면 form태그의 submit이 기본으로 작동한다. 

 

 

 

2. 

[board.js]

let index = {
    init: function(){
        $("#btn-reply-save").on("click", ()=>{     // 등록 버튼 클릭시
            this.replySave();
        });
    },

// 댓글 쓰기
replySave: function() {
    let data = {
        content: $("#reply-content").val()    // textarea 내용
    };

    let boardId = $("#boardId").val();   // .val() 안붙이면 int 타입 
 
    $.ajax({
        //댓글 쓰기 수행 요청
        type: "POST",
        url: `/api/board/${boardId}/reply`,  // 백틱 씀
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json"
    }).done(function(resp) {
        alert("댓글 작성이 완료되었습니다.");
        location.href = `/board/${boardId}`;  // 해당 게시글 이동
    }).fail(function(error) {
        alert(JSON.stringify(error));
    });
},

 

- let boardId = $("#boardId").val();를 붙여야 String으로 된다. 

타입이 String이여야 location.href = `/board/${boardId}`;  댓글 완료 후 해당 게시글로 이동이 됨!

 

 

- data에 boardId: $("#boardId").val() 를 넣을 필요가 없는 이유

아래의 ajax 댓글 쓰기 수행할때 url:`/api/board/${boardId}/reply` 주소에 이미 넣기 때문에 boardId 값을 data에 넣을필요는 없다

 

 

백틱 사용

url에 `백틱` 을 사용하면 ${}를 사용해서 문자열과 변수를 적절히 같이 사용할 수 있다.

  • url:`/api/board/${boardId}/reply`, → 자바스크립트의 변수값이 String 문자열로 바꾸기 위해 백틱을 쓴다. 
  • location.href=`/board/${boardId}`

 

 

 

3.

이제 주소 /api/board/${boardId}/reply 를 만들자

[BoardApiController]

//댓글작성
@PostMapping("/api/board/{boardId}/reply")
public ResponseDto<Integer> replySave(@PathVariable int boardId, @RequestBody Reply reply, @AuthenticationPrincipal PrincipalDetail principal) { 
    boardService.댓글쓰기(principal.getUser(), boardId, reply);
    return new ResponseDto<Integer>(HttpStatus.OK.value(), 1); //자바 오브젝트를 JSON으로 변환해서 리턴
}
  • @RequestBody Reply reply : reply를 받을때 reply 안에 content가 필요하니까 (내가 작성한 댓글)
  • @AuthenticationPrincipal PrincipalDetail principal : 누가 적은지 알아야해서

댓글쓰기에는 "유저id" / "게시글 id" / "댓글" 이렇게 3가지를 날린다.  

 

 

 

 

4.

댓글쓰기() 메서드 만들기

[boardService]

@Autowired private
ReplyRepository replyRepository;

@Transactional
public void 댓글쓰기(User user, int boardId, Reply requestReply) {  // 요청받은 reply

    Board board = boardRepository.findById(boardId)
            .orElseThrow(()->{
                return new IllegalArgumentException("댓글 작성 실패 : 게시글 id를 찾을 수 없습니다.");
            });

    requestReply.setUser(user);
    requestReply.setBoard(board);   // boardId는 findById를 통해서 넣는다.

    replyRepository.save(requestReply);   // user,board오브젝트를 넣은것
}

 

 

-결과

 

 

 


 

댓글삭제

댓글삭제도 ajax 를 통해 비동기 처리 

 

1.

[detail.jsp]

<div class="card">
    <div class="card-header">댓글 리스트</div>
    <ul id="reply-box" class="list-group">
        <c:forEach var="reply" items="${board.replys}">

            <li id="reply-${reply.id}" class="list-group-item d-flex justify-content-between">
                <div>${reply.content}</div>
                <div class="d-flex">
                    <div class="font-italic">작성자 : ${reply.user.username} &nbsp;</div>
                    <c:if test="${reply.user.id eq principal.user.id}">
                        <button onClick="index.replyDelete(${board.id}, ${reply.id})" class="badge">삭제</button>
                    </c:if>
                </div>
            </li>

        </c:forEach>
    </ul>
</div>

 

자신이 쓴 댓글만 삭제 가능하도록

<c:if test="${reply.user.id == principal.user.id }">
    <button onclick="index.replyDelete(${board.id}, ${reply.id})" class="badge">삭제</button>
</c:if>

 

onClick="index.replyDelete(${board.id}, ${reply.id})"  

함수이름을 index.replyDelete() 하고 어떤 게시글인지, 어떤 댓글인지 알기위해 파라미터를 두개 넣는다. 

 

 

 

 

2.

[board.js]

 

** onClick 함수라서 아래처럼 쓸 필요가 없음.

let index = {
		init: function(){
			$("#btn-save").on("click", ()=>{ 
				this.save();
			});

 

 

boardId, replyId 파라미터 두개를 받는다. 

// 댓글 삭제
replyDelete: function(boardId, replyId) {
    $.ajax({
        //댓글 쓰기 수행 요청
        type: "DELETE",
        url: `/api/board/${boardId}/reply/${replyId}`,
        dataType: "json"
    }).done(function(resp) {
        alert("댓글 삭제 성공.");
        location.href = `/board/${boardId}`;
    }).fail(function(error) {
        alert(JSON.stringify(error));
    });
},

데이터를 들고올게 아니라서 data 나 contentType이 필요없다

 

 

 

 

/api/board/${boardId}/reply/${replyId} 주소 만들기

 

3.

[BoardApiController]

@DeleteMapping("/api/board/${boardId}/reply/${replyId}")
public ResponseDto<Integer> replyDelete(@PathVariable int replyId){   // replyId 만으로 삭제가능
    boardService.댓글삭제(replyId);
    return new ResponseDto<Integer>(HttpStatus.OK.value(),1);
}

replyId 만 있으면 삭제가 되기때문에 replyId 만 받으면 된다.

boardId 는 주소를 만들기위해 받은것뿐

 

 

 

4.

[BoardService]

@Transactional
public void 댓글삭제(int replyId) {
    replyRepository.deleteById(replyId);
}

 

반응형
LIST

+ Recent posts