등록버튼을 눌렀을 때 해당 textarea를 찾아서 값을 가져오기
textarea.val()
방법1) this의 previous 형제를 찾기
방법2) this의 parent를 찾고 거기서 textarea 자식을 찾기
select reply_renum_seq.currval from dual => 현재 시퀀스의 번호 가져오기
from dual
한번에 vo객체를 가져오려면 (beanutil 사용)
BeanUtils.populate(vo, request.getParameterMap());
게시글 클릭시 - 그 글번호에 해당하는 댓글 리스트가 출력되어야 함
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<script src="../js/board.js"></script>
<style>
body{
margin: 10px;
}
.p1{
width: 80%;
padding: 5px;
margin: 3px;
float: left;
}
.p2{
width: 17%;
padding: 5px;
margin: 2px;
float: right;
}
.p3{
clear: both;
}
input[name=reply]{
height: 40px;
vertical-align: top;
}
.pager{
width: 100px;
float: left;
margin: 5px;
margin-left: 5%;
}
</style>
<script type="text/javascript">
currentPage = 1;
reply = { } // 객체 선언 - 속성과 메서드를 동적으로 추가해서 사용
$(function(){
listPage(currentPage);
//이벤트
$('#list').on('click', '.action', function(){
//또는 $(document).on('click', '.action', function(){})
idx = $(this).attr('idx');
name = $(this).attr('name');
if(name=="modify"){
alert(idx + "번째 글을 수정합니다");
}else if(name=="delete"){
alert(idx + "번째 글을 삭제합니다");
}else if(name=="reply"){
alert(idx + "번째 글에 댓글을 답니다");
text = $(this).prev().val();
console.log(text);
// 숫자에 해당하는 대문자가 나옴
name1 = String.fromCharCode(Math.random() * 26 + 65);
name2 = String.fromCharCode(Math.random() * 26 + 97);
name3 = parseInt(Math.random() * 100 + 1);
// name, text
reply.name = name1 + name2 + name3;
reply.bonum = idx;
reply.cont = text;
// 서버로 전송 $.ajax({})
replyInsert(this); // 댓글저장 - 등록버튼 객체
//insert에서는 안쓰고 list에서 씀
//this객체가 insert에서는 필요없고 list에서 사용하기때문에 파라미터로 넘겨줌
//댓글리스트
replyList();
//비동기방식이라서 요청 - 응답의 순서가 아님
}
});
//페이지번호 리스트 이벤트
$('#pagelist').on('click', '.paging', function(){
currentPage = $(this).text().trim();
listPage(currentPage);
});
//next 이벤트
$('#pagelist').on('click', '.next', function(){
currentPage = parseInt($('.paging').last().text().trim()) + 1;
listPage(currentPage);
});
//pre 이벤트
$('#pagelist').on('click', '.prev', function(){
currentPage = parseInt($('.paging').first().text().trim()) - 1;
listPage(currentPage);
});
});//$(function)
</script>
</head>
<body>
<h2>게시판</h2>
<br>
<div id="list"></div>
<div id="pagelist"></div>
</body>
</html>
/**
*
*/
function replyList(brep){
//idx에 해당하는 댓글을 가져온다
//리스트를 가져오는 ajax 수행
$.ajax({
url : '/board/ReplyList.do',
type : 'get',
data : {'bonum' : idx }, // reply는 댓글 저장 전에 생긴 것(생성되기 전) - idx대신 reply.bonum은 사용 못함
success : function(res){
//성공
//댓글 리스트 출력
rcode = '';
$.each(res, function(i,v){
rcode +='<div class="panel-body repl"> ';
rcode +='<p class="p1"> ';
rcode +='<span class="wr">'+ v.name +'</span> ';
rcode +='날짜 :<span class="wd">' + v.date + '</span> ';
rcode +='</p> ';
rcode +=' ';
rcode +='<p class="p2"> ';
rcode +='<input idx="'+ v.renum +'" type="button" name="r_modify" class="action" value="댓글수정"> ';
rcode +='<input idx="'+ v.renum +'" type="button" name="r_delete" class="action" value="댓글삭제"> ';
rcode +='</p> ';
rcode +='<p class="p3"> ';
rcode += v.cont;
rcode +='</p> ';
rcode += '</div>';
});// $.each
$(brep).parents('.panel').find('.pbody').append(rcode); //find - 밑으로 내려가면서 찾는 것(후손)
},
error : function(xhr){
alert("상태 : " + xhr.status);
},
dataType : 'json'
});
/**/
}
function replyInsert(brep){ // brep - 클릭한 button객체
$.ajax({
url : '/board/ReplyInsert.do',
type : 'post',
data : reply,
success : function(res){
//저장 성공 - res.sw
//댓글 리스트 출력
replyList(brep);
},
error : function(xhr){
alert("상태 : " + xhr.status);
},
dataType : 'json'
});
}
function listPage(cpage){
$.ajax({
url:"/board/List.do",
data: { "page" : cpage},
type: 'get',
success: function(res){
code = '<div class="panel-group" id="accordion">';
$.each(res.datas ,function(i,v){
code +='<div class="panel panel-default">';
code +='<div class="panel-heading">';
code +='<h4 class="panel-title"> ';
code +='<a data-toggle="collapse" data-parent="#accordion" href="#collapse'+ v.num +'">'+ v.subject +'</a> ';
code +='</h4> ';
code +='</div> ';
code +='<div id="collapse'+ v.num +'" class="panel-collapse collapse"> ';
code +='<div class="panel-body pbody"> ';
code +='<p class="p1"> ';
code +='작성자 :<span class="wr">'+ v.writer +'</span> ';
code +='이메일 :<span class="em">'+ v.mail +'</span> ';
code +='조회수 :<span class="hit">'+ v.hit +'</span> ';
code +='날짜 :<span class="wd">' + v.wdate + '</span> ';
code +='</p> ';
code +=' ';
code +='<p class="p2"> ';
code +='<input idx="'+ v.num +'" type="button" name="modify" class="action" value="수정"> ';
code +='<input idx="'+ v.num +'" type="button" name="delete" class="action" value="삭제"> ';
code +='</p> ';
code +='<p class="p3"> ';
code +='내용출력 내용출력<br> ';
code += v.content;
code +='</p> ';
code +='<p class="p4"> ';
code +=' <textarea rows="" cols="100"></textarea> ';
code +=' <input idx="'+ v.num +'" type="button" value="등록" name="reply" class="action"> ';
code +=' ';
code +=' </p> ';
code +=' </div> ';
code +=' </div> ';
code +='</div> ';
});
code += '</div>';
$('#list').html(code);
$('#pagelist').empty();
//이전버튼만들기
if(res.sp > 1){
pager = '<ul class="pager">';
pager += '<li><a class="prev" href="#">Previous</a></li>';
pager += '</ul>';
$('#pagelist').append(pager);
}
/*<ul class="pager">
<li><a href="#">Previous</a></li>
<li><a href="#">Next</a></li>
</ul>
*/
//페이지번호 만들기
pager = '<ul class="pagination pager">';
for(i=res.sp; i <=res.ep; i++){
if(cpage == i){
pager += '<li class="active"><a class="paging" href="#">' + i + '</a></li>';
}else{
pager += '<li><a class="paging" href="#">' + i + '</a></li>';
}
}
pager += '</ul>';
$('#pagelist').append(pager);
//다음버튼 만들기
if(res.ep < res.tp){
pager = '<ul class="pager">';
pager += '<li><a class="next" href="#">Next</a></li>';
pager += '</ul>';
$('#pagelist').append(pager);
}
},
error: function(xhr){
alert("상태 : " + xhr.status);
},
dataType: 'json'
});
} //listPage
package kr.or.ddit.board.controller;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import kr.or.ddit.board.service.BoardServiceImpl;
import kr.or.ddit.board.service.IBoardService;
import kr.or.ddit.board.vo.ReplyVO;
/**
* Servlet implementation class ReplyInsert
*/
@WebServlet("/ReplyInsert.do")
public class ReplyInsert extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
//0. 클라이언트 요청 시 전송
ReplyVO vo = new ReplyVO();
try {
BeanUtils.populate(vo, request.getParameterMap());
} catch (IllegalAccessException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
vo.setBonum(Integer.parseInt(request.getParameter("bonum")));
vo.setName(request.getParameter("name"));
vo.setCont(request.getParameter("cont"));
//1. service 객체 얻어오기
IBoardService service = BoardServiceImpl.getInstance();
//2.
int rnum = service.insertReply(vo);
//3.
request.setAttribute("rnum", rnum);
//
request.getRequestDispatcher("board/result.jsp").forward(request, response);
}
}
package kr.or.ddit.board.controller;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import kr.or.ddit.board.service.BoardServiceImpl;
import kr.or.ddit.board.service.IBoardService;
import kr.or.ddit.board.vo.ReplyVO;
/**
* Servlet implementation class ReplyList
*/
@WebServlet("/ReplyList.do")
public class ReplyList extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//0. 클라이언트 요청 시 전송 값 가져오기 : bonum
int bonum = Integer.parseInt(request.getParameter("bonum"));
//1. service객체
IBoardService service = BoardServiceImpl.getInstance();
//2. service메서드
List<ReplyVO> list = service.listReply(bonum);
//3.
request.setAttribute("list", list);
//4.
request.getRequestDispatcher("board/replyList.jsp").forward(request, response);
}
}
<%@page import="kr.or.ddit.board.vo.ReplyVO"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//서블릿에서 실행 결과 공유
List<ReplyVO> list = (List<ReplyVO>)request.getAttribute("list");
%>
[
<%
for(int i = 0; i <list.size(); i++){
ReplyVO vo = list.get(i);
if(i > 0) out.print(",");
%>
{
"renum" : "<%= vo.getRenum() %>",
"bonum" : "<%= vo.getBonum() %>",
"name" : "<%= vo.getName() %>",
"cont" : "<%= vo.getCont().replaceAll("\r", "").replaceAll("\n", "<br>") %>",
"date" : "<%= vo.getRedate() %>"
}
<%
}
%>
]
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap
PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"
"http://ibatis.apache.org/dtd/sql-map-2.dtd">
<sqlMap namespace="reply">
<insert id="insertReply" parameterClass="replyVO">
insert into reply(renum, bonum, name, cont, redate)
values(
reply_renum_seq.nextval,
#bonum#,
#name#,
#cont#,
sysdate
)
<selectKey keyProperty="renum" resultClass="int">
select reply_renum_seq.currval from dual
</selectKey>
</insert>
<select id="listReply" resultClass="replyVO" parameterClass="int">
select * from reply where bonum = #bonum#
</select>
</sqlMap>