DataBases
DB
create table mbanswer(idx smallint auto_increment primary key,
num smallint,
name varchar(20),
myid varchar(30),
content varchar(500),
writeday datetime,
foreign key(num) references memboard(num) on delete cascade);
num
은 첨부 대상 게시물의 시퀀스이므로 foreign key
로 연결하고 on delete cascade
조건 추가
- 댓글 자체의 시퀀스는
idx
Mapper
@Mapper
public interface AnswerMapperInter {
public void insertMbanswer(MbanswerDto dto);
public List<MbanswerDto> getAllAnswers(String num);
public MbanswerDto getAnswer(String idx);
public void updateAnswer(MbanswerDto dto);
public void deleteAnswer(String idx);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="boot.data.mapper.MbanswerMapperInter">
<insert id="insertMbanswer" parameterType="mbdto">
insert into mbanswer values(null,#{num},#{name},#{myid},#{content},now())
</insert>
<select id="getAllAnswers" parameterType="String" resultType="mbdto">
select * from mbanswer where num=#{num} order by idx desc
</select>
<select id="getAnswer" parameterType="String" resultType="mbdto">
select * from mbanswer where idx=#{idx}
</select>
<update id="updateAnswer" parameterType="mbdto">
update mbanswer set content=#{content} where idx=#{idx}
</update>
<delete id="deleteAnswer" parameterType="String">
delete from mbanswer where idx=#{idx}
</delete>
</mapper>
- 댓글은 게시물에 첨부되는 데이터이므로, 게시물의 시퀀스(
num
)와 댓글의 시퀀스(idx
)를 잘 구별하여야 함
JavaScript
$(function(){
list();
});
function list(){
var s="";
num=$("#num").val();
var loginok="${sessionScope.loginok}";
var myid="${sessionScope.myid}";
$.ajax({
data:{"num":num},
dataType:"json",
type:"get",
url:"/mbanswer/alist",
success:function(res){
$.each(res,function(i,e){
s+="<b>"+e.name+"("+e.myid+") : </b>";
s+="<span check='check'>"+e.content+"</span> ";
if(loginok!=null&&myid==e.myid){
s+="<i class='bi bi-recycle amod' idx='"+e.idx+"'></i> ";
s+="<i class='bi bi-trash-fill adel' idx='"+e.idx+"'></i><br>";
}else{
s+="<br>";
}
});
$("div.alist").html(s);
$("span.acount").text(res.length);
}
});
}
- DB에 존재하는 댓글 중 게시물에 해당하는 모든 댓글을 출력하는 함수 (
list()
)
- 해당 파일이 구동되는 동시에 댓글이 출력되어야 하므로 기본적으로 해당 함수 작동
- 게시물을 식별할 시퀀스 전달 (
num
)
- JavaScript에서 Java의
Session
을 사용하기 위해서는 JSTL의 EL(${ }
)과 sessionScope
를 사용하되, 문자열 형태로 호출 가능
- 출력할 내용 : 댓글 내용, 수정 버튼, 삭제 버튼, 댓글 개수
- 수정, 삭제 버튼은 자신이 작성한 댓글에만 조건부로 출력 (
if()
)
<br>
의 위치가 조건부에 따라 달라지므로 유의
- Ajax를 통해 돌아오는 데이터가
List<dto>
이므로 반복 함수($.each()
: 각 댓글 정보)의 인자 데이터를 사용할지, 반복되는 개별 데이터(dto
, e
: 댓글 전체 정보)를 사용할지 유의
Ajax Controller
@Controller
@RequestMapping("/mbanswer")
public class MbanswerController {
@Autowired
MbanswerMapperInter mapper;
@GetMapping("/alist")
public @ResponseBody List<MbanswerDto> list(@RequestParam String num){
return mapper.getAllAnswers(num);
}
}
<tr>
<td>
<div class="alist"></div>
<input type="hidden" id="num" value="${dto.num }">
<c:if test="${sessionScope.loginok!=null }">
<div class="aform">
<div class="d-inline-flex">
<input type="text" class="form-control" id="content">
<button type="button" id="btnasnweradd">등록</button>
</div>
</div>
</c:if>
</td>
</tr>
- 게시물 상세 페이지의 일부 (댓글 입력 파트)
- 어떤 게시물에 첨부된 댓글인지를 구분할 게시물의 시퀀스인
num
을 hidden
으로 입력
Event_JavaScript
$(function(){
list();
$("#btnasnweradd").on("click",function(){
var num=$("#num").val();
var content=$("#content").val();
if(content==""){
alert("댓글을 입력해주세요");
return;
}else{
$.ajax({
data:{"num":num,"content":content},
dataType:"html",
type:"post",
url:"/mbanswer/ainsert",
success:function(res){
$("#content").val("");
list();
}
});
}
});
});
- 삽입 후에는 댓글 입력 창 초기화 및 삽입한 댓글 포함한 전체 댓글 리스트 출력(
list()
)
- 공백 댓글 시 입력 반려
Controller
@Controller
@RequestMapping("/mbanswer")
public class MbanswerController {
@Autowired
MbanswerMapperInter mapper;
@PostMapping("/ainsert")
public @ResponseBody void insert(@ModelAttribute("mbdto") MbanswerDto mbdto,
HttpSession session) {
String check=mbdto.getContent().trim();
if(!check.equals("")) {
mbdto.setMyid((String)session.getAttribute("myid"));
mbdto.setName((String)session.getAttribute("loginname"));
mapper.insertMbanswer(mbdto);
}
}
}
View
Event_JavaScript
$(function(){
$(document).on("click","i.adel",function(){
var idx=$(this).attr("idx");
$.ajax({
data:{"idx":idx},
dataType:"html",
type:"post",
url:"/mbanswer/adelete",
success:function(res){
list();
}
});
});
});
- Ajax 이벤트 완료 후 항상 변경 사항 포함한 리스트 재출력 (
list()
)
- 삭제용 Mapper(Sql), Controller 생략
View
Event_JaveScript
$(function(){
$(document).on("click","i.amod",function(){
var content=$(this).prev().text();
var idx=$(this).attr("idx");
var check=$(this).prev().attr("check");
if(check=="check"){
$(this).prev().remove();
$(this).hide();
$(this).next().hide();
$("#content").hide();
$("#btnasnweradd").hide();
var s="";
s+="<div class='d-inline-flex'>";
s+="<span>댓글 수정</span>";
s+="<input type='text' id='modacontent' class='form-control' value='"+content+"' autofocus='autofocus'> ";
s+="<button type='button' class='btn btn-outline-warning' id='modclear' idx='"+idx+"'>수정완료</button>";
s+="</div>";
$(this).before(s);
}
});
});
- DB의 댓글 내용을 미리 확보 후, 내용을 포함하는 태그 제거
- 댓글 수정 작업하는 동안은 기존 댓글 작성창은 비활성화 (
hide()
)
- 동적 이벤트로 수정할 내용을 입력할 창과 수정된 내용을 이벤트로 등록할 버튼 동적 생성
Event_JavaScript
$(function(){
$(document).on("click","#modclear",function(){
var idx=$(this).attr("idx");
var content=$(this).prev().val();
$.ajax({
data:{"idx":idx,"content":content},
dataType:"html",
type:"post",
url:"/mbanswer/aupdate",
success:function(res){
list();
$("#content").show();
$("#btnasnweradd").show();
}
});
});
});
Controller
@Controller
@RequestMapping("/mbanswer")
public class MbanswerController {
@Autowired
MbanswerMapperInter mapper;
@PostMapping("/aupdate")
public @ResponseBody void update(String idx,String content) {
MbanswerDto mbdto=mapper.getAnswer(idx);
mbdto.setIdx(idx);
mbdto.setContent(content);
mapper.updateAnswer(mbdto);
}
}