resources 폴더 안에 있는 js폴더에 reply.js 파일 생성 후 작성


/**
*
*/
console.log("Reply");
var replyService = (function(){
function add(reply, callback){
console.log("reply......");
$.ajax({
type : "post",
url : reply.contextPath + "/replies/new",
data : JSON.stringify(reply),
contentType : "application/json; charset=utf-8",
success : function(result, status, xhr) {
if (callback) {
callback(result);
}
},
error : function(xhr, status, er) {
if (error) {
error(er);
}
}
})
}
return {
add : add
};
})();
read.jsp 파일에 js파일 연결 후 테스트 코드 작성

<script src="${ctx }/resources/js/reply.js"></script>
<script>
$(function(){
console.log(replyService);
var bnoValue = "${board.bno}";
replyService.add(
{replytext: "js test1", replyer: "user01", bno: bnoValue, contextPath: "${ctx}"},
function(result) {
alert("result : " + result);
}
);
});
</script>
톰캣 구동 후 상세페이지로 들어가서 alert 창이 잘 뜨는지 확인

DB에 잘 등록되었는지 확인

ReplyMapper.xml 하단의 getListWithPaging select문 수정

<select id="getListWithPaging" resultType="com.hanul.springstudent.domain.ReplyDTO">
<![CDATA[
SELECT rno,
bno,
replytext,
replyer,
regdate,
updatedate
FROM (SELECT /*+ INDEX(tbl_reply IDX_tbl_reply_PK) */
rownum rn,
rno,
bno,
replytext,
replyer,
regdate,
updatedate
FROM tbl_reply
WHERE bno = #{bno}
AND rno > 0
AND rownum <= #{cri.pageNum} * #{cri.amount})
WHERE rn > (#{cri.pageNum} - 1) * #{cri.amount}
]]>
</select>
ReplyMapper 클래스에 코드 추가

public int getCountByBno(int bno);
ReplyMapper.xml 하단의 getCountByBno select문 추가

<select id="getCountByBno" resultType="int">
<![CDATA[
SELECT count(rno)
FROM tbl_reply
WHERE bno = #{bno}
]]>
</select>
domain 패키지에 ReplyPageDTO 생성 후 작성

@Data
@AllArgsConstructor
public class ReplyPageDTO {
private int replyCnt;
private List<ReplyDTO> list;
}
IReplyService 인터페이스에 추상메소드 추가

public ReplyPageDTO getListPage(Criteria cri, int bno);
ReplyServiceImpl 에서 추상메소드 구현

@Override
public ReplyPageDTO getListPage(Criteria cri, int bno) {
return new ReplyPageDTO(
mapper.getCountByBno(bno),
mapper.getListWithPaging(cri, bno));
}
ReplyController 에 코드추가 후 상단에 있는 getList 메소드는 주석처리

@GetMapping(value = "/pages/{bno}/{page}",
produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public ResponseEntity<ReplyPageDTO> getList(@PathVariable("page") int page, @PathVariable("bno") int bno) {
Criteria cri = new Criteria(page, 10);
log.info("get reply list bno : " + bno);
log.info("cri : " + cri);
return new ResponseEntity<>(service.getListPage(cri, bno), HttpStatus.OK);
}
reply.js 코드 작성

/**
*
*/
console.log("Reply Module........");
var replyService = (function() {
function add(reply, callback, error) {
console.log("add reply.................");
$.ajax({
type : "post",
url : reply.contextPath + "/replies/new",
data : JSON.stringify(reply),
contentType : "application/json; charset=utf-8",
success : function(result, status, xhr) {
if (callback) {
callback(result);
}
},
error : function(xhr, status, er) {
if (error) {
error(er);
}
}
})
}
// 댓글 목록
function getList(param, callback, error) {
var bno = param.bno;
var page = param.page || 1;
var contextPath = param.contextPath;
$.getJSON(contextPath + "/replies/pages/" + bno + "/" + page,
function(data) {
if (callback) {
callback(data.replyCnt, data.list);
}
}).fail(function(xhr, status, err) {
if (error) {
error();
}
});
}
// 댓글 삭제
function remove(reply, callback, error) {
$.ajax({
type : "delete",
url : reply.contextPath + "/replies/" + reply.rno,
success : function(deleteResult, status, xhr) {
if (callback) {
callback(deleteResult);
}
},
error : function(xhr, status, er) {
if (error) {
error(er);
}
}
});
}
// 댓글 수정
function update(reply, callback, error) {
console.log("RNO: " + reply.rno);
$.ajax({
type : "put",
url : reply.contextPath + "/replies/" + reply.rno,
data : JSON.stringify(reply),
contentType : "application/json; charset=utf-8",
success : function(result, status, xhr) {
if (callback) {
callback(result);
}
},
error : function(xhr, status, er) {
if (error) {
error(er);
}
}
});
}
// 댓글 조회
function get(reply, callback, error) {
$.get(reply.contextPath + "/replies/" + reply.rno, function(result) {
if (callback) {
callback(result);
}
}).fail(function(xhr, status, err) {
if (error) {
error();
}
});
}
// 댓글 시간 처리
function displayTime(timeValue) {
var today = new Date();
var gap = today.getTime() - timeValue;
var dateObj = new Date(timeValue);
var str = "";
if (gap < (1000 * 60 * 60 * 24)) {
var hh = dateObj.getHours();
var mi = dateObj.getMinutes();
var ss = dateObj.getSeconds();
return [ (hh > 9 ? '' : '0') + hh, ':', (mi > 9 ? '' : '0') + mi,
':', (ss > 9 ? '' : '0') + ss ].join('');
} else {
var yy = dateObj.getFullYear();
var mm = dateObj.getMonth() + 1; // getMonth() is zero-based
var dd = dateObj.getDate();
return [ yy, '/', (mm > 9 ? '' : '0') + mm, '/',
(dd > 9 ? '' : '0') + dd ].join('');
}
}
return {
add : add,
get : get,
getList : getList,
remove : remove,
update : update,
displayTime : displayTime
}
})();
read.jsp 파일에 댓글 목록과 등록/수정 모달 코드 추가

<!-- 댓글 목록 처리 -->
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-comment fa-fw"></i>Reply
<button id="addReplyBtn" class="btn btn-primary btn-xs pull-right">New Reply</button>
</div>
<div class="panel-body">
<ul class="chat">
</ul>
</div>
<div class="panel-footer">
</div>
</div>
</div>
</div>
<!-- 신규 댓글 모달 -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title" id="myModalLabel">REPLY MODAL</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label>ReplyText</label>
<input class="form-control" name="replytext" value="New Reply!!!!">
</div>
<div class="form-group">
<label>Replyer</label>
<input class="form-control" name="replyer" value="replyer">
</div>
<div class="form-group">
<label>Reply Date</label>
<input class="form-control" name="replyDate" value="2024-01-01 13:13">
</div>
</div>
<div class="modal-footer">
<button id="modalModifyBtn" type="button" class="btn btn-warning">Modify</button>
<button id="modalRemoveBtn" type="button" class="btn btn-danger">Remove</button>
<button id="modalRegisterBtn" type="button" class="btn btn-primary">Register</button>
<button id="modalCloseBtn" type="button" class="btn btn-default">Close</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!-- /.modal -->
하단에 제이쿼리 추가
<script type="text/javascript">
$(document).ready(function() {
var bnoValue = "${board.bno}";
var replyUL = $(".chat");
showList(1);
function showList(page) {
console.log("show list " + page);
replyService.getList(
{bno:bnoValue, contextPath:"${contextPath}", page: page || 1 },
function(replyCnt, list) {
console.log("replyCnt: "+ replyCnt );
console.log("list: " + list);
console.log(list);
if(page == -1){
pageNum = Math.ceil(replyCnt/10.0);
showList(pageNum);
return;
}
var str="";
if(list == null || list.length == 0){
return;
}
for (var i = 0, len = list.length || 0; i < len; i++) {
str +="<li class='left clearfix' data-rno='"+list[i].rno+"'>";
str +=" <div><div class='header'><strong class='primary-font'>["
+ list[i].rno+"] "+list[i].replyer+"</strong>";
str +=" <small class='pull-right text-muted'>"
+ replyService.displayTime(list[i].updatedate)+"</small></div>";
str +=" <p>"+list[i].replytext+"</p></div></li>";
}
replyUL.html(str);
showReplyPage(replyCnt);
});//end function
}//end showList
var pageNum = 1;
var replyPageFooter = $(".panel-footer");
function showReplyPage(replyCnt) {
var endNum = Math.ceil(pageNum / 10.0) * 10;
var startNum = endNum - 9;
var prev = startNum != 1;
var next = false;
if(endNum * 10 >= replyCnt) {
endNum = Math.ceil(replyCnt/10.0);
}
if(endNum * 10 < replyCnt) {
next = true;
}
var str = "<ul class='pagination pull-right'>";
if(prev) {
str+= "<li class='page-item'><a class='page-link' href='"+(startNum -1)+"'>Previous</a></li>";
}
for(var i = startNum ; i <= endNum; i++) {
var active = pageNum == i? "active":"";
str+= "<li class='page-item "+active+" '><a class='page-link' href='"+i+"'>"+i+"</a></li>";
}
if(next) {
str+= "<li class='page-item'><a class='page-link' href='"+(endNum + 1)+"'>Next</a></li>";
}
str += "</ul></div>";
console.log(str);
replyPageFooter.html(str);
}
replyPageFooter.on("click","li a", function(e) {
e.preventDefault();
console.log("page click");
var targetPageNum = $(this).attr("href");
console.log("targetPageNum: " + targetPageNum);
pageNum = targetPageNum;
showList(pageNum);
});
var modal = $(".modal");
var modalInputReplyText = modal.find("input[name='replytext']");
var modalInputReplyer = modal.find("input[name='replyer']");
var modalInputReplyDate = modal.find("input[name='replyDate']");
var modalModifyBtn = $("#modalModifyBtn");
var modalRemoveBtn = $("#modalRemoveBtn");
var modalRegisterBtn = $("#modalRegisterBtn");
$("#modalCloseBtn").on("click", function(e){
modal.modal("hide");
});
$("#addReplyBtn").on("click", function(e){
modal.find("input").val("");
modalInputReplyDate.closest("div").hide();
modal.find("button[id !='modalCloseBtn']").hide();
modalRegisterBtn.show();
$(".modal").modal("show");
});
modalRegisterBtn.on("click", function(e) {
var reply = {
replytext: modalInputReplyText.val(),
replyer:modalInputReplyer.val(),
contextPath:"${contextPath}",
bno:bnoValue
};
replyService.add(reply, function(result){
alert(result);
modal.find("input").val("");
modal.modal("hide");
showList(-1);
});
});
$(".chat").on("click", "li", function(e){
var reply = {
rno : $(this).data("rno"),
contextPath:"${contextPath}",
};
replyService.get(reply, function(reply){
modalInputReplyText.val(reply.replytext);
modalInputReplyer.val(reply.replyer);
modalInputReplyDate.val(replyService.displayTime(reply.regdate)).attr("readonly","readonly");
modal.data("rno", reply.rno);
modal.find("button[id !='modalCloseBtn']").hide();
modalModifyBtn.show();
modalRemoveBtn.show();
$(".modal").modal("show");
});
});
modalModifyBtn.on("click", function(e){
var reply = {
rno:modal.data("rno"),
replytext: modalInputReplyText.val(),
contextPath:"${contextPath}"
};
replyService.update(reply, function(result) {
alert(result);
modal.modal("hide");
showList(pageNum);
});
});
modalRemoveBtn.on("click", function (e) {
var reply = {
rno : modal.data("rno"),
contextPath:"${contextPath}"
};
replyService.remove(reply, function(result) {
alert(result);
modal.modal("hide");
showList(pageNum);
});
});
});
</script>
그리고 내 로컬호스트 상세페이지에 들어가서 댓글이 잘 뜨는지 확인

'Programming > Spring' 카테고리의 다른 글
[STS3] 댓글 기능(4) (0) | 2024.04.24 |
---|---|
[STS3] 트랜잭션 (0) | 2024.04.24 |
[STS3] 댓글 기능(2) (0) | 2024.04.22 |
[STS3] 댓글 기능(1) (0) | 2024.04.22 |
[STS3] 파일 업로드(1) (0) | 2024.04.22 |