스프링 백엔드 - 프로젝트 생성 후 postman으로 테스트, 대댓글 작성법 설명
리액트 첫 시간
대댓글, 컨트롤러와
대댓글은 entity 부분만 잘 이해하고 만들면 어렵지 않음
2시 115분 녹화 영상 보기 comments1/src/main/resources/templates/board/view.html at master · sifter0926/comments1
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6"
layout:decorate="~{layout/basic.html}">
<div layout:fragment="content">
<div class="container mt-3">
<h3>Board View</h3>
<br />
<div class="form-group">
<label for="num">글번호:</label>
<input type="text" class="form-control" id="num" name="num" th:value="${board.num}" readonly="readonly">
</div>
<div class="form-group">
<label for="title">제목:</label>
<input type="text" class="form-control" id="title" name="title" th:value="${board.title}" readonly="readonly">
</div>
<div class="form-group">
<label for="writer">글쓴이:</label>
<input type="text" class="form-control" id="writer" name="writer" th:value="${board.writer}" readonly="readonly">
</div>
<div class="form-group">
<label for="content">내용:</label>
<textarea name="content" id="content" class="form-control" readonly="readonly">[[${board.content }]]</textarea>
</div>
<div class="form-group">
<label for="regDate">등록일:</label>
<input type="text" class="form-control" id="regDate" name="regdate" th:value="${board.regdate}" readonly="readonly">
</div>
<div class="form-group">
<label for="writer">조회수:</label>
<input type="text" class="form-control" id="hitcount" name="hitcount" th:value="${board.hitcount}" readonly="readonly">
</div>
<div class="form-group">
<label for="replycount">댓글 수:</label>
<input type="text" class="form-control" id="replycount" name="replycount" th:value="${board.replycount}" readonly="readonly">
</div>
<div class="form-group mt-5">
<span sec:authorize="isAuthenticated()" th:if="${#authentication.principal.username==board.getWriter()}">
<a th:href="|@{/board/modify(num=${board.num})}|">
<button type="button" id="btnUpdate" class="btn btn-secondary">수정</button>
</a>
<a th:href="|@{/board/delete(num=${board.num})}|">
<button type="button" id="btnDelete" class="btn btn-danger">삭제</button>
</a>
</span>
<a th:href="|@{/board/list}|">
<button type="button" id="btnList" class="btn btn-info">List</button>
</a>
</div>
</div>
<!-- 댓글 영역-->
<div class="row mt-3">
<div class="col-md-12">
<div class="my-4 ">
<button sec:authorize="isAuthenticated()" class="btn btn-info addCommentBtn">ADD Comment</button>
</div>
<ul class="list-group commentList"> //여기에 댓글 리스트가 나옴. 그래서 ul 적어두신 것
댓글 리스트 영역
</ul>
</div>
</div>
<div class="row mt-3">
<div class="col">
<ul class="pagination commentPaging">
</ul>
</div>
</div>
<div class="modal registerModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Register Replyer</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="input-group mb-3">
<span class="input-group-text">Reply Text</span>
<input type="text" class="form-control replyText" >
</div>
<div class="input-group mb-3">
<span class="input-group-text">Replyer</span>
<input type="text" class="form-control replyer" >
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary registerBtn">Register</button>
<button type="button" class="btn btn-outline-dark closeRegisterBtn" >Close</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="/js/comment.js"></script>
</div>
<script layout:fragment="script" th:inline="javascript"> //이 부분이 꼭 필요함
const board_id=[[${board.num}]]
const commentList = document.querySelector('.commentList') //댓글 목록 DOM
let str =''
function printList(dtoList){ //댓글 목록 출력 //DTO리스트가 옴
//console.log(dtoList)
if(dtoList && dtoList.length > 0){
for (const dto of dtoList) { //dto 리스트에 있는 것을 가져옴
str += `<li class="list-group-item d-flex commentItem">
<span class="col-1">${dto.id}</span>
<span class="col-6" data-rno="${dto.id}">${dto.content}</span>
<span class="col-2">${dto.writer}</span>
<span class="col-2">${dto.regdate} </span>
<button class="btn btn-outline-dark addReplyBtn" data-cno="${dto.id}">댓글작성</button> //대댓글을 넣기 위한 버튼
</li>`
if(dto.children && dto.children.length >0){ //재귀호출 현재 나는 printlist임 chilren이 없을 때까지 돌면서 뿌리는 원리
str+=' <ul>'
printList(dto.children)
str+=' </ul>'
}
}
}
commentList.innerHTML = str; //str 만든 것을 뿌려줌 (str은 115열부터 123열까지 끝나고, 만약 대댓글이 있으면 또 이걸 돌면서 화면에 뿌려줌
}
function printComments(){ //이걸 그대로 뿌리면 같은 것이 여러번 뿌려짐. 그래서 새로 댓글을 추가하면 또 list를 가져오게 되므로 printComments에서 다시 초기화를 함
str=''
commentList.clear //초기화
getList(board_id).then( // getList는 axios로 연결한 것을 만들어 둔 곳에서 가져옴
data => {
//console.log((data))
printList(data) //목록 처리 //뿌림
//printPages(data) //페이지 처리
}
).catch(e => {
console.error(e)
})
}
printComments(); //페이지가 열리자마자 printComments 호출해서 화면에 뿌리는 역할 -> 데이터 가져옴 -> printlist로 가서 뿌림
const registerModal = new bootstrap.Modal(document.querySelector(".registerModal"))
//registerModel
const registerBtn = document.querySelector(".registerBtn")
const replyText = document.querySelector(".replyText")
const replyer = document.querySelector(".replyer")
const closeRegisterBtn = document.querySelector(".closeRegisterBtn")
let parentId='' // parentId는 값이 바뀌므로 let으로 선언함
document.querySelector(".addCommentBtn").addEventListener("click", function (e){
//replyer.value=writer
registerModal.show() //모달을 띄움
},false)
closeRegisterBtn.addEventListener("click", function (e){
registerModal.hide()
},false)
registerBtn.addEventListener("click", function(e){
let commentObj=null
if(parentId=='') { // parentId가 공백
commentObj = {
content: replyText.value,
writer: replyer.value,
}
}else{
commentObj = {
content: replyText.value,
writer: replyer.value,
parentId : parentId
}
}
addComment(commentObj, board_id).then(result => { //comment.js에 이 부분 만든 부분 있음
alert(result) //이부분이 결과가 나오는 것임
registerModal.hide() //add누른 후에 모달 닫고, 값 지워서 새로 뿌릴 수 있게 준비
replyText.value = ''
replyer.value =''
printComments() //댓글 목록 갱신
}).catch(e => {
alert("Exception...")
})
}, false)
//대댓글 추가 영역
//const replyModal = new bootstrap.Modal(document.querySelector(".replyModal"))
//registerModel
const addReplyBtn=document.querySelector(".commentList")
addReplyBtn.addEventListener("click", function (e){
parentId=e.target.getAttribute("data-cno")
registerModal.show()
},false)
</script>
</html>
async function getList(bno) {
const result = await axios.get(`/comments/${bno}`) //axios와 연결함
console.log(result.data) //이런식으로 테스트하면서 하기
return result.data; //result에서 data 즉, 댓글 리스트를 가져옴
}
// async function getList({bno, page, size, goLast}){
//
// const result = await axios.get(`/comments/${bno}`, {params: {page, size}})
//
// if(goLast){
// const total = result.data.total
// const lastPage = parseInt(Math.ceil(total/size))
// return getList({bno:bno, page:lastPage, size:size})
// }
//
// return result.data
// }
async function addComment(commentObj, boardId) {
const response = await axios.post(`/comments/${boardId}`,commentObj)
return response.data
}
async function addReComment(commentObj, parentId) {
const response = await axios.post(`/comments/${parentId}`,commentObj)
return response.data
}
async function getComment(id) {
const response = await axios.get(`/comments/${id}`)
return response.data
}
async function modifyComment(commentObj) {
const response = await axios.put(`/comments/${commentObj.id}`, replyObj)
return response.data
}
async function removeComment(id) {
const response = await axios.delete(`/comments/${id}`)
return response.data
}
comments1/src/main/resources/static/js/comment.js at master · sifter0926/comments1
comments1/src/main/resources/static/js/comment.js at master · sifter0926/comments1
Contribute to sifter0926/comments1 development by creating an account on GitHub.
github.com
comments1/src/main/resources/templates/board/view.html at master · sifter0926/comments1
comments1/src/main/resources/templates/board/view.html at master · sifter0926/comments1
Contribute to sifter0926/comments1 development by creating an account on GitHub.
github.com
여기서 위의 자바스크립트 함수를 호출함 printComments 함수를 호출함
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity6"
layout:decorate="~{layout/basic.html}">
<div layout:fragment="content">
<div class="container mt-3">
<h3>Board View</h3>
<br />
<div class="form-group">
<label for="num">글번호:</label>
<input type="text" class="form-control" id="num" name="num" th:value="${board.num}" readonly="readonly">
</div>
<div class="form-group">
<label for="title">제목:</label>
<input type="text" class="form-control" id="title" name="title" th:value="${board.title}" readonly="readonly">
</div>
<div class="form-group">
<label for="writer">글쓴이:</label>
<input type="text" class="form-control" id="writer" name="writer" th:value="${board.writer}" readonly="readonly">
</div>
<div class="form-group">
<label for="content">내용:</label>
<textarea name="content" id="content" class="form-control" readonly="readonly">[[${board.content }]]</textarea>
</div>
<div class="form-group">
<label for="regDate">등록일:</label>
<input type="text" class="form-control" id="regDate" name="regdate" th:value="${board.regdate}" readonly="readonly">
</div>
<div class="form-group">
<label for="writer">조회수:</label>
<input type="text" class="form-control" id="hitcount" name="hitcount" th:value="${board.hitcount}" readonly="readonly">
</div>
<div class="form-group">
<label for="replycount">댓글 수:</label>
<input type="text" class="form-control" id="replycount" name="replycount" th:value="${board.replycount}" readonly="readonly">
</div>
<div class="form-group mt-5">
<span sec:authorize="isAuthenticated()" th:if="${#authentication.principal.username==board.getWriter()}">
<a th:href="|@{/board/modify(num=${board.num})}|">
<button type="button" id="btnUpdate" class="btn btn-secondary">수정</button>
</a>
<a th:href="|@{/board/delete(num=${board.num})}|">
<button type="button" id="btnDelete" class="btn btn-danger">삭제</button>
</a>
</span>
<a th:href="|@{/board/list}|">
<button type="button" id="btnList" class="btn btn-info">List</button>
</a>
</div>
</div>
<!-- 댓글 영역-->
<div class="row mt-3">
<div class="col-md-12">
<div class="my-4 ">
<button sec:authorize="isAuthenticated()" class="btn btn-info addCommentBtn">ADD Comment</button>
</div>
<ul class="list-group commentList">
댓글 리스트 영역
</ul>
</div>
</div>
<div class="row mt-3">
<div class="col">
<ul class="pagination commentPaging">
</ul>
</div>
</div>
<div class="modal registerModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Register Replyer</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="input-group mb-3">
<span class="input-group-text">Reply Text</span>
<input type="text" class="form-control replyText" >
</div>
<div class="input-group mb-3">
<span class="input-group-text">Replyer</span>
<input type="text" class="form-control replyer" >
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary registerBtn">Register</button>
<button type="button" class="btn btn-outline-dark closeRegisterBtn" >Close</button>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="/js/comment.js"></script>
</div>
<script layout:fragment="script" th:inline="javascript">
const board_id=[[${board.num}]]
const commentList = document.querySelector('.commentList') //댓글 목록 DOM
let str =''
function printList(dtoList){ //댓글 목록 출력
//console.log(dtoList)
if(dtoList && dtoList.length > 0){
for (const dto of dtoList) {
str += `<li class="list-group-item d-flex commentItem">
<span class="col-1">${dto.id}</span>
<span class="col-6" data-rno="${dto.id}">${dto.content}</span>
<span class="col-2">${dto.writer}</span>
<span class="col-2">${dto.regdate} </span>
<button class="btn btn-outline-dark addReplyBtn" data-cno="${dto.id}">댓글작성</button>
//현재 댓글의 아이디를 가져와서 대댓글을 쓸 수 잇음...?? 2시 36분 영상 다시 보기
</li>`
if(dto.children && dto.children.length >0){
str+=' <ul>'
printList(dto.children)
str+=' </ul>'
}
}
}
commentList.innerHTML = str;
}
function printComments(){
str=''
commentList.clear
getList(board_id).then(
data => {
//console.log((data))
printList(data) //목록 처리
//printPages(data) //페이지 처리
}
).catch(e => {
console.error(e)
})
}
printComments();
const registerModal = new bootstrap.Modal(document.querySelector(".registerModal"))
//registerModel
const registerBtn = document.querySelector(".registerBtn")
const replyText = document.querySelector(".replyText")
const replyer = document.querySelector(".replyer")
const closeRegisterBtn = document.querySelector(".closeRegisterBtn")
let parentId=''
document.querySelector(".addCommentBtn").addEventListener("click", function (e){
//replyer.value=writer
registerModal.show()
},false)
closeRegisterBtn.addEventListener("click", function (e){
registerModal.hide()
},false)
registerBtn.addEventListener("click", function(e){
let commentObj=null
if(parentId=='') {
commentObj = {
content: replyText.value,
writer: replyer.value,
}
}else{
commentObj = {
content: replyText.value,
writer: replyer.value,
parentId : parentId
}
}
addComment(commentObj, board_id).then(result => {
alert(result)
registerModal.hide()
replyText.value = ''
replyer.value =''
printComments() //댓글 목록 갱신
}).catch(e => {
alert("Exception...")
})
}, false)
//대댓글 추가 영역
//const replyModal = new bootstrap.Modal(document.querySelector(".replyModal"))
//registerModel
const addReplyBtn=document.querySelector(".commentList")
addReplyBtn.addEventListener("click", function (e){
parentId=e.target.getAttribute("data-cno")
registerModal.show()
},false)
</script>
</html>