사용 기술
요구사항
방식 | 호출 대상 | 파라미터 | 작업 | 반환되는 데이터 |
GET | /replies/board/{bno} (게시물 번호) | 게시물 번호 | 해당 게시물의 댓글들 조회 | JSON 배열 |
POST | /replies/ | JSON으로 구성된 댓글 데이터 | 댓글 추가 | 추가된 댓글의 번호 |
DELETE | /replies/{rno} | 댓글의 번호 | 댓글 삭제 | 삭제 결과 문자열 |
PUT | /replies/{rno} | 댓글의 번호 + 수정할 내용 | 댓글 수정 | 수정 결과 문자열 |
# JSON과 Ajax로 댓글 처리
:REST 방식이라는 다양한 방식의 호출을 이용해 댓글 처리
-> 모든 댓글은 게시물 조회 화면에서 처리, Ajax를 이용해 컨트롤러와 JSON으로 데이터를 교환
- 게시물 로딩 후에, 화면의 댓글 숫자 클릭시 -> 댓글 가져옴 [비동기 방식인 Ajax로 처리]
- 특정 버튼 클릭시 새로운 댓글 입력 창 띄우고, 댓글 전송 [비동기 방식인 Ajax로 POST방식으로 전달]
이후, 댓글 목록을 새로 가져와 방금 추가한 댓글 보여준다 [화면 전체 새로고침이 아닌, 댓글 부분만 가져오는 Ajax로 처리] - 댓글 삭제와 수정은 모달창에서 처리, 모든 댓글의 수정/삭제 가능 [이후에 추가]
댓글 엔티티
: Board를 ToString()에서 제외 후, Board클래스와의 다대일 연관관계를 LAZY로딩으로 설정
package com.board.boot3.entity;
import lombok.*;
import javax.persistence.*;
@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString(exclude = "board")
public class Reply extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long rno;
private String text;
private String replyer;
@ManyToOne
private Board board;
}
1. ReplyRepository에서 특정 게시물 번호에 해당하는 댓글을 가져오도록 변경
: Board객체를 파라미터로 받아, 모든 댓글을 순번대로 가져온다.
package com.board.boot3.repository;
import com.board.boot3.entity.Board;
import com.board.boot3.entity.Reply;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface ReplyRepository extends JpaRepository<Reply, Long> {
//게시물에 있는 댓글 테이블까지 CASCADE옵션으로 삭제
//1. 해당 게시물의 모든 댓글 삭제
//2. 해당 게시물 삭제
//3. 이 작업은 하나의 트랜잭션
//게시물 번호로 댓글 삭제
//->Update, delete 를 위한 어노테이션
@Modifying
@Query("delete from Reply r where r.board.bno =:bno ")
void deleteByBno(@Param("bno") Long bno);
//특정 게시물 번호로 댓글 가져오기
List<Reply> getRepliesByBoardOrderByRno(Board board);
}
게시물 번호를 통해 해당 댓글을 가져오는 테스트
//특정 게시물 번호로 댓글 가져오는 테스트
@Test
public void testListByBoard() {
List<Reply> replyList = replyRepository.getRepliesByBoardOrderByRno(
Board.builder().bno(97L).build());
replyList.forEach(reply -> System.out.println(reply));
}
2. 서비스 계층과 ReplyDTO 처리
: 서비스에 entityToDTO, dtoToEntity 메서드 추가하고 구현 클래스 작성
댓글 기능
-> 게시물 자체에 대한 참조가 아닌 게시물 번호로 참조하도록 변경
ReplyDTO
: 댓글 엔티티와 달리, 게시물 번호만 가지는 형태
package com.board.boot3.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Data
public class ReplyDTO {
private Long rno;
private String text;
private String replyer;
private Long bno; //게시글 번호
private LocalDateTime regDate, modDate;
}
ReplyService
: 추상메서드 선언
(1) 댓글 등록 기능
(2) 특정 게시글의 댓글을 가져오는 기능
(3) 댓글 수정 기능
(4) 댓글 삭제 기능
: 디폴트 메서드 작성
(1) dtoToEntity()
: Board객체 처리를 위해,Board 엔티티 객체를 작성해 객세 생성 후, Reply 엔티티 생성시, 생성한 Board엔티티 삽입해 전달
(2) entityToDto()
package org.zerock.board.service;
import org.zerock.board.dto.ReplyDTO;
import org.zerock.board.entity.Board;
import org.zerock.board.entity.Reply;
import java.util.List;
public interface ReplyService {
Long register(ReplyDTO replyDTO); //댓글의 등록
List<ReplyDTO> getList(Long bno); //특정 게시물의 댓글 목록
void modify(ReplyDTO replyDTO); //댓글 수정
void remove(Long rno); //댓글 삭제
//ReplyDTO를 Reply객체로 변환 Board객체의 처리가 수반됨
default Reply dtoToEntity(ReplyDTO replyDTO){
Board board = Board.builder().bno(replyDTO.getBno()).build();
Reply reply = Reply.builder()
.rno(replyDTO.getRno())
.text(replyDTO.getText())
.replyer(replyDTO.getReplyer())
.board(board)
.build();
return reply;
}
//Reply객체를 ReplyDTO로 변환 Board 객체가 필요하지 않으므로 게시물 번호만
default ReplyDTO entityToDTO(Reply reply){
ReplyDTO dto = ReplyDTO.builder()
.rno(reply.getRno())
.text(reply.getText())
.replyer(reply.getReplyer())
.regDate(reply.getRegDate())
.modDate(reply.getModDate())
.build();
return dto;
}
}
ReplyServiceImpl
(1) 댓글 등록 기능 구현
: 엔티티를 가져와 DTO로 변경 후, 리포지토리에 엔티티 저장
-> 수행 후, 댓글 번호 반환
(2) 특정 게시글의 댓글을 가져오는 기능 구현
: 글 번호를 받아와, 해당 글의 댓글을 모두 리스트로 넣고, 특정 게시글의 댓글을 가져오는 메서드를 호출한다.
(파라미터는 게시물 엔티티로 객체 생성해 전달)
-> 리스트로 만든 엔티티를 DTO로 만들어 다시 리스트로 저장해 반환
(3) 댓글 수정 기능 구현
: 댓글 DTO를 받아 엔티티로 바꾸고,
-> 리포지토리에 엔티티 저장
(4) 댓글 삭제 기능 구현
: 리포지토리에서 댓글 아이디의 댓글 삭제하는 메서드를 호출
package com.board.boot3.service;
import com.board.boot3.dto.ReplyDTO;
import com.board.boot3.entity.Board;
import com.board.boot3.entity.Reply;
import com.board.boot3.repository.ReplyRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class ReplyServiceImpl implements ReplyService {
private final ReplyRepository replyRepository;
@Override
public Long register(ReplyDTO replyDTO) {
Reply reply = dtoToEntity(replyDTO);
replyRepository.save(reply);
return reply.getRno();
}
@Override
public List<ReplyDTO> getList(Long bno) {
List<Reply> result = replyRepository
.getRepliesByBoardOrderByRno(Board.builder().bno(bno).build());
return result.stream().map(reply -> entityToDTO(reply)).collect(Collectors.toList());
}
@Override
public void modify(ReplyDTO replyDTO) {
Reply reply = dtoToEntity(replyDTO);
replyRepository.save(reply);
}
@Override
public void remove(Long rno) {
replyRepository.deleteById(rno);
}
}
댓글을 번호로 가져오는 테스트 출력 : 엔티티 처리 테스트
@Test
public void testGetList() {
Long bno = 100L;//데이터베이스에 존재하는 번호
List<ReplyDTO> replyDTOList = service.getList(bno);
replyDTOList.forEach(replyDTO -> System.out.println(replyDTO));
}
# @RestController 적용
: 조회 화면에서 Ajax로 댓글 표시
댓글 데이터를 JSON으로 만들어서 처리, 화면 없이 데이터만 전송하므로 @RestController 이용
-> RestController의 경우 기본 리턴 타입으로 JSON을 사용한다
@RestController: REST 방식 처리 위한 어노테이션
:@ResponseBody 가 포함된 어노테이션으로, JSON이나 XML 방식으로 리턴한다.
-> ResponseEntity<> 타입을 사용하는데, 해당 타입은 데이터뿐 아니라 상태코드도 함께 전송되는 특징이 있다.
//@ResponseBody 포함 : 데이터와 상태코드 함께 전송
@RestController
@RequestMapping("/replies/")
@Log4j2
@RequiredArgsConstructor
public class ReplyController {
private final ReplyService replyService;
//게시물 댓글 목록 가져오는 URL
@GetMapping(value = "/board/{bno}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<ReplyDTO>> getListByBoard(@PathVariable("bno") Long bno ){
log.info("bno: " + bno);
return new ResponseEntity<>( replyService.getList(bno), HttpStatus.OK);
}
즉, 특정 게시물 번호로 조회시, 100이라는 데이터를 변수로 처리하는 것이 가능하다.
화면에서 처리하도록 list.html 변경
: 클래스 속성 값을 추가해 구분이 쉽도록 처리 (replyCount, replyList)
<a th:href="@{/board/list(page=${requestDTO.page})}">
<button type="button" class="btn btn-info">List</button>
</a>
<div >
<div class="mt-4">
<h5 ><span class="badge badge-info addReply">Add Reply</span> </h5>
<h5 ><span class="badge badge-secondary replyCount"> Reply Count [[${dto.replyCount}]]</span> </h5>
</div>
<div class="list-group replyList">
</div>
</div>
버튼 이벤트 처리를 위한 자바스크립트
(1) 화면 로딩이 끝나면 함수를 수행한다
(2) 글 번호를 가져와 bno 변수에 저장
(3) replyList 변수를 가져와, listGroup 변수에 저장
(4) 해당 글의 댓글들을 JSON으로 받아서 출력
<script th:inline="javascript">
$(document).ready(function() {
var bno = [[${dto.bno}]];
var listGroup = $(".replyList");
$(".replyCount").click(function(){
$.getJSON('/replies/board/'+bno, function(arr){
console.log(arr);
})//end getJSON
})//end click
}));
</script>
댓글 처리 위한 화면
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<th:block th:replace="~{/layout/basic :: setContent(~{this::content} )}">
<th:block th:fragment="content">
<h1 class="mt-4">Board Read Page</h1>
<div class="form-group">
<label >Bno</label>
<input type="text" class="form-control" name="gno" th:value="${dto.bno}" readonly >
</div>
<div class="form-group">
<label >Title</label>
<input type="text" class="form-control" name="title" th:value="${dto.title}" readonly >
</div>
<div class="form-group">
<label >Content</label>
<textarea class="form-control" rows="5" name="content" readonly>[[${dto.content}]]</textarea>
</div>
<div class="form-group">
<label >Writer</label>
<input type="text" class="form-control" name="writer" th:value="${dto.writerName}" readonly>
</div>
<div class="form-group">
<label >RegDate</label>
<input type="text" class="form-control" name="regDate" th:value="${#temporals.format(dto.regDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
</div>
<div class="form-group">
<label >ModDate</label>
<input type="text" class="form-control" name="modDate" th:value="${#temporals.format(dto.modDate, 'yyyy/MM/dd HH:mm:ss')}" readonly>
</div>
<a th:href="@{/board/modify(bno = ${dto.bno}, page=${requestDTO.page})}">
<button type="button" class="btn btn-primary">Modify</button>
</a>
<a th:href="@{/board/list(page=${requestDTO.page})}">
<button type="button" class="btn btn-info">List</button>
</a>
<div >
<div class="mt-4">
<h5 ><span class="badge badge-info addReply">Add Reply</span> </h5>
<h5 ><span class="badge badge-secondary replyCount"> Reply Count [[${dto.replyCount}]]</span> </h5>
</div>
<div class="list-group replyList">
</div>
</div>
댓글만 따로 처리하기 위한 댓글 조회 기능 분리
: 댓글 추가되거나 삭제시 화면의 갱신이 필요하기 때문에 별도의 함수로 분리
//댓글이 추가될 영역
var listGroup = $(".replyList");
//날짜 처리를 위한 함수
function formatTime(str) {
var date = new Date(str);
return date.getFullYear() + '/' +
(date.getMonth() + 1) + '/' +
date.getDate() + ' ' +
date.getHours() + ':' +
date.getMinutes();
}
//특정한 게시글의 댓글을 처리하는 함수
function loadJSONData() {
$.getJSON('/replies/board/' + bno, function (arr) {
console.log(arr);
var str = "";
$('.replyCount').html(" Reply Count " + arr.length);
$.each(arr, function (idx, reply) {
console.log(reply);
str += ' <div class="card-body" data-rno="' + reply.rno + '"><b>' + reply.rno + '</b>';
str += ' <h5 class="card-title">' + reply.text + '</h5>';
str += ' <h6 class="card-subtitle mb-2 text-muted">' + reply.replyer + '</h6>';
str += ' <p class="card-text">' + formatTime(reply.regDate) + '</p>';
str += ' </div>';
})
listGroup.html(str);
});
}
데이터 처리해 갱신
->Ajax를 이용해 가져온 JSON를 이용해 화면상의 댓글을 숫자로 갱신, 화면에 필요한 태그를 만들어 댓글 목록에 추가
-> 화면 표시 날짜는 formatTime()함수로 처리하고
-> 댓글 숫자 클릭시 동작
//처리한 데이터를 클릭시 보여주는 함수
$(".replyCount").click(function () {
loadJSONData();
})//end click
댓글 추가와 모달창 설정
: 댓글 추가 클릭시 모달창 보여주고 새로운 댓글 추가 -> 수정과 삭제시에도 동일하게 사용하는 모달창
모달 창 화면
내부 : replyText, replyer, rno인 input타입 태그를 가지도록 설정
버튼 : 저장, 닫기, 수정, 삭제 버튼 추가
<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true"></span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<input class="form-control" type="text" name="replyText" placeholder="Reply Text...">
</div>
<div class="form-group">
<input class="form-control" type="text" name="replyer" placeholder="Replyer">
<input type="hidden" name="rno" >
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger replyRemove">Remove</button>
<button type="button" class="btn btn-warning replyModify">Modify</button>
<button type="button" class="btn btn-primary replySave">Save</button>
<button type="button" class="btn btn-outline-secondary replyClose" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
모달 창화면 이벤트 처리
//모달 창
var modal = $('.modal');
$(".addReply").click(function () {
modal.modal('show');
//댓글 입력하는 부분 초기화 시키기
$('input[name="replyText"]').val('');
$('input[name="replyer"]').val('');
$(".modal-footer .btn").hide(); //모달 내의 모든 버튼을 안 보이도록
$(".replySave, .replyClose").show(); //필요한 버튼들만 보이도록
});
read.html의 [자바스크립트]
<script th:inline="javascript">
$(document).ready(function() {
var bno = [[${dto.bno}]];
var listGroup = $(".replyList");
$(".replyCount").click(function () {
$.getJSON('/replies/board/' + bno, function (arr) {
console.log(arr);
})//end getJSON
})//end click
//댓글이 추가될 영역
var listGroup = $(".replyList");
//날짜 처리를 위한 함수
function formatTime(str) {
var date = new Date(str);
return date.getFullYear() + '/' +
(date.getMonth() + 1) + '/' +
date.getDate() + ' ' +
date.getHours() + ':' +
date.getMinutes();
}
//특정한 게시글의 댓글을 처리하는 함수
function loadJSONData() {
$.getJSON('/replies/board/' + bno, function (arr) {
console.log(arr);
var str = "";
$('.replyCount').html(" Reply Count " + arr.length);
$.each(arr, function (idx, reply) {
console.log(reply);
str += ' <div class="card-body" data-rno="' + reply.rno + '"><b>' + reply.rno + '</b>';
str += ' <h5 class="card-title">' + reply.text + '</h5>';
str += ' <h6 class="card-subtitle mb-2 text-muted">' + reply.replyer + '</h6>';
str += ' <p class="card-text">' + formatTime(reply.regDate) + '</p>';
str += ' </div>';
})
listGroup.html(str);
});
}
$(".replyCount").click(function () {
loadJSONData();
})//end click
//모달 창
var modal = $('.modal');
$(".addReply").click(function () {
modal.modal('show');
//댓글 입력하는 부분 초기화 시키기
$('input[name="replyText"]').val('');
$('input[name="replyer"]').val('');
$(".modal-footer .btn").hide(); //모달 내의 모든 버튼을 안 보이도록
$(".replySave, .replyClose").show(); //필요한 버튼들만 보이도록
});
});
</script>
-> 댓글 추가 시, 모달창을 화면에서 숨기고, 게시물의 댓글을 가져와 화면 갱신
#등록
: 댓글 데이터를 ajax를 이용해 등록 처리
컨트롤러단
:@RequestBody를 이용해 JSON으로 들어오는 데이터를 해당 타입으로의 객체 매핑해준다.
-> JSON데이터를 특정 객체로 변환해서 처리하기 좋다.
//댓글 데이터 전송하는 POST방식
@PostMapping("")
public ResponseEntity<Long> register(@RequestBody ReplyDTO replyDTO){
log.info(replyDTO);
Long rno = replyService.register(replyDTO);
return new ResponseEntity<>(rno, HttpStatus.OK);
}
-> ResponseEntity를 이용해 객체 반환하는데, 댓글 번호와 HTTP상태를 같이 보낸다.
화면단 [read.html]
$(".replySave").click(function() {
var reply = {
bno: bno,
text: $('input[name="replyText"]').val(),
replyer: $('input[name="replyer"]').val()
}
console.log(reply);
$.ajax({
url: '/replies/',
method: 'post',
data: JSON.stringify(reply),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function(data){
console.log(data);
var newRno = parseInt(data);
alert(newRno +"번 댓글이 등록되었습니다.")
modal.modal('hide');
loadJSONData();
}
})
});
-> 댓글 등록시 댓글번호 알려준다.
#삭제
댓글의 삭제 처리
: 댓글 번호만 전송하면 되지만, RestController를 이용할 경우 DELETE방식을 이용해 데이터를 전송한다.
-> 특정 댓글 선택해 모달창에서 삭제
컨트롤러단 -> DeleteMapping
@DeleteMapping("/{rno}")
public ResponseEntity<String> remove(@PathVariable("rno") Long rno) {
log.info("RNO:" + rno );
replyService.remove(rno);
return new ResponseEntity<>("success", HttpStatus.OK);
}
리스트를 보여주고 삭제 처리 수행
$('.replyList').on("click", ".card-body", function(){
var rno = $(this).data("rno");
$("input[name='replyText']").val( $(this).find('.card-title').html());
$("input[name='replyer']").val( $(this).find('.card-subtitle').html());
$("input[name='rno']").val(rno);
$(".modal-footer .btn").hide();
$(".replyRemove, .replyModify, .replyClose").show();
modal.modal('show');
});
$(".replyRemove").on("click", function(){
var rno = $("input[name='rno']").val(); //모달 창에 보이는 댓글 번호 hidden처리되어 있음
$.ajax({
url: '/replies/' + rno,
method: 'delete',
success: function(result){
console.log("result: " + result);
if(result ==='success'){
alert("댓글이 삭제되었습니다");
modal.modal('hide');
loadJSONData();
}
}
})
});
-> div내에 data-rno 속성으로 댓글 번호 저장, 제목과 내용은 CSS의 클래스를 이용해 처리
-> 해당 변수는 JSON으로 받아온 댓글 번호
$.each(arr, function (idx, reply) {
console.log(reply);
str += ' <div class="card-body" data-rno="' + reply.rno + '"><b>' + reply.rno + '</b>';
str += ' <h5 class="card-title">' + reply.text + '</h5>';
str += ' <h6 class="card-subtitle mb-2 text-muted">' + reply.replyer + '</h6>';
str += ' <p class="card-text">' + formatTime(reply.regDate) + '</p>';
str += ' </div>';
})
-> 삭제완료시 alert를 이용해 알림
#수정
댓글의 수정 처리
: PUT방식을 사용하는데, 댓글 번호, 게시물 번호, 내용, 작성자를 같이 전송
-> 하나의 객체로 구성해 JSON 형태로 전달, 서버에서 JSON 데이터를 ReplyDTO로 변환해 처리
컨트롤러단
//댓글 데이터 수정하는 POST방식
@PutMapping("/{rno}")
public ResponseEntity<String> modify(@RequestBody ReplyDTO replyDTO) {
log.info(replyDTO);
replyService.modify(replyDTO);
return new ResponseEntity<>("success", HttpStatus.OK);
}
화면단
$(".replyModify").click(function() {
var rno = $("input[name='rno']").val();
var reply = {
rno: rno,
bno: bno,
text: $('input[name="replyText"]').val(),
replyer: $('input[name="replyer"]').val()
}
console.log(reply);
$.ajax({
url: '/replies/' + rno,
method: 'put',
data: JSON.stringify(reply),
contentType: 'application/json; charset=utf-8',
success: function(result){
console.log("RESULT: " + result);
if(result ==='success'){
alert("댓글이 수정되었습니다");
modal.modal('hide');
loadJSONData();
}
}
});
});
-> Ajax에서 문자열로 success결과를 이용해 처리한다.
list
<script th:inline="javascript">
var msg = [[${msg}]];
console.log(msg);
if(msg){
$(".modal").modal();
}
var searchForm = $("#searchForm");
$('.btn-search').click(function(e){
searchForm.submit();
});
$('.btn-clear').click(function(e){
searchForm.empty().submit();
});
</script>
read
<script th:inline="javascript">
$(document).ready(function() {
var bno = [[${dto.bno}]];
var listGroup = $(".replyList");
$(".replyCount").click(function () {
//'/replies/board/' + bno 여기서 받은 값을 arr에 넣고, JSON에서 출력한다.
$.getJSON('/replies/board/' + bno, function (arr) {
console.log(arr);
})//end getJSON
})//end click
//댓글이 추가될 영역
var listGroup = $(".replyList");
//날짜 처리를 위한 함수
function formatTime(str) {
var date = new Date(str);
return date.getFullYear() + '/' +
(date.getMonth() + 1) + '/' +
date.getDate() + ' ' +
date.getHours() + ':' +
date.getMinutes();
}
//특정한 게시글의 댓글을 처리하는 함수
function loadJSONData() {
$.getJSON('/replies/board/' + bno, function (arr) {
console.log(arr);
var str = "";
$('.replyCount').html(" Reply Count " + arr.length);
$.each(arr, function (idx, reply) {
console.log(reply);
str += ' <div class="card-body" data-rno="' + reply.rno + '">';
str += ' <h5 class="card-title">' + reply.text + '</h5>';
str += ' <h6 class="card-subtitle mb-2 text-muted">' + reply.replyer + '</h6>';
str += ' <p class="card-text">' + formatTime(reply.regDate) + '</p>';
str += ' </div>';
})
listGroup.html(str);
});
}
//처리한 데이터를 클릭시 보여주는 함수
$(".replyCount").click(function () {
loadJSONData();
})//end click
//댓글 추가를 위한 모달창 만들고, 수정 및 삭제 때도 이용할 수 있도록 작성
//모달 창
var modal = $('.modal');
$(".addReply").click(function () {
modal.modal('show');
//댓글 입력하는 부분 초기화 시키기
$('input[name="replyText"]').val('');
$('input[name="replyer"]').val('');
$(".modal-footer .btn").hide(); //모달 내의 모든 버튼을 안 보이도록
$(".replySave, .replyClose").show(); //필요한 버튼들만 보이도록
});
//댓글 저장 버튼 클릭시, 실제 댓글 등록 작업 처리
//-> 새로운 댓글들은 JSON 형태의 데이터를 처리하므로, 자바스크립트 객체 생성후
//해당 객체를 JSON.stringify()로 JSON 문자열로 바꾸어 전송
$(".replySave").click(function() {
//자바스크립트 객체 생성
var reply = {
bno: bno,
text: $('input[name="replyText"]').val(),
replyer: $('input[name="replyer"]').val()
}
console.log(reply);
$.ajax({
url: '/replies/',
method: 'post',
data: JSON.stringify(reply),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function(data){
console.log(data);
var newRno = parseInt(data);
alert(newRno +"번 댓글이 등록되었습니다.")
modal.modal('hide');
loadJSONData();
}
})
});
$('.replyList').on("click", ".card-body", function(){
var rno = $(this).data("rno");
$("input[name='replyText']").val( $(this).find('.card-title').html());
$("input[name='replyer']").val( $(this).find('.card-subtitle').html());
$("input[name='rno']").val(rno);
$(".modal-footer .btn").hide();
$(".replyRemove, .replyModify, .replyClose").show();
modal.modal('show');
});
$(".replyRemove").on("click", function(){
var rno = $("input[name='rno']").val(); //모달 창에 보이는 댓글 번호 hidden처리되어 있음
$.ajax({
url: '/replies/' + rno,
method: 'delete',
success: function(result){
console.log("result: " + result);
if(result ==='success'){
alert("댓글이 삭제되었습니다");
modal.modal('hide');
loadJSONData();
}
}
})
});
$(".replyModify").click(function() {
var rno = $("input[name='rno']").val();
var reply = {
rno: rno,
bno: bno,
text: $('input[name="replyText"]').val(),
replyer: $('input[name="replyer"]').val()
}
console.log(reply);
$.ajax({
url: '/replies/' + rno,
method: 'put',
data: JSON.stringify(reply),
contentType: 'application/json; charset=utf-8',
success: function(result){
console.log("RESULT: " + result);
if(result ==='success'){
alert("댓글이 수정되었습니다");
modal.modal('hide');
loadJSONData();
}
}
});
});
});
</script>
modify
<script th:inline="javascript">
var actionForm = $("form"); //form 태그 객체
$(".removeBtn").click(function(){
actionForm
.attr("action", "/board/remove")
.attr("method","post");
actionForm.submit();
});
$(".modifyBtn").click(function() {
if(!confirm("수정하시겠습니까?")){
return ;
}
actionForm
.attr("action", "/board/modify")
.attr("method","post")
.submit();
});
$(".listBtn").click(function() {
//var pageInfo = $("input[name='page']");
var page = $("input[name='page']");
// var type = $("input[name='type']");
// var keyword = $("input[name='keyword']");
actionForm.empty(); //form 태그의 모든 내용을 지우고
actionForm.append(page);
// actionForm.append(type);
// actionForm.append(keyword);
actionForm
.attr("action", "/board/list")
.attr("method","get");
actionForm.submit();
})
</script>
'Server Programming > Spring Boot Backend Programming' 카테고리의 다른 글
[Spring 부트 - 영화 리뷰 프로젝트] 2. 파일 업로드 처리 (1) Ajax를 통한 JSON으로 이미지 업로드 (0) | 2022.10.18 |
---|---|
[Spring 부트 - 영화 리뷰 프로젝트] 1. M:N (다대다) 관계 설계와 구현 [+ N+1 문제와 엔티티의 특정 속성 로딩 방법] (0) | 2022.10.17 |
[Spring 부트 - 댓글 프로젝트] 3-2. 게시물과 댓글, 컨트롤러와 화면 처리 [자바스크립트] (1) | 2022.10.03 |
[Spring 부트 - 댓글 프로젝트] 3-1. N:1 연관관계의 게시물과 댓글 CRUD (1) | 2022.10.03 |
[Spring 부트 - 방명록 미니 프로젝트] 2-3. 서비스, DTO, 컨트롤러 작성 (2) (0) | 2022.10.02 |