[KH정보교육원 당산] 75일(AJAX - To-Do-List )
어제 했더 예제의 연속
main.jsp
<div class="all">
<table id="thTable" class="headerTable">
<tr>
<td class="headerTable">
<div class="title">
<h1>나의 해야할 일들</h1>
</div>
</td>
<td class="headerTable"></td>
<td class="headerTable">
<div class="button">
<form action="TodoForm">
<input type="submit" value="새로운 TODO 등록">
</form>
</div>
</td>
</tr>
</table>
<!-- <table id="thTable" class="headerTable"> -->
<!-- main.jsp에서는 전달받은 결과를 JSTL 과 EL을 이용해 출력. -->
<div class="context">
<!-- 해야 할일 TODO -->
<div>
<table id="todo">
<tr>
<th>TODO : 해야 할 일</th>
</tr>
<c:forEach var="todo" items="${todoList }">
<c:if test="${todo.type=='TODO' }">
<tr id="${todo.id }">
<td class="todoUpdate">
<b>${todo.title}</b><br />
등록날짜:${todo.regdate}, ${todo.name}, 우선순위${todo.sequence}
<button data-id="${todo.id}" data-type="${todo.type}">></button>
</td>
</tr>
</c:if>
</c:forEach>
</table>
<!-- <table id="todo"> -->
</div>
<!-- <div class="context"> -->
<!-- 현재 작업 중인 TODO -->
<div>
<table id="doing">
<tr>
<th>DOING : 현재 하고 있는 일</th>
</tr>
<c:forEach var="todo" items="${todoList}">
<c:if test="${todo.type=='DOING'}">
<tr id="${todo.id}">
<td class="todoUpdate">
<b>${todo.title}</b><br />
등록날짜:${todo.regdate}, ${todo.name}, 우선순위${todo.sequence}
<button data-id="${todo.id}" data-type="${todo.type}">☞</button>
</td>
</tr>
</c:if>
</c:forEach>
</table>
<!-- <table id="doing"> -->
</div>
<!-- 작업 완료된 TODO -->
<div>
<table id="done">
<tr>
<th>DONE : 작업이 완료된 일들</th>
</tr>
<c:forEach var="todo" items="${todoList}">
<c:if test="${todo.type=='DONE'}">
<tr id="${todo.id}">
<td class="todoUpdate">
<b>${todo.title}</b><br />
등록날짜:${todo.regdate}, ${todo.name}, 우선순위${todo.sequence}
</td>
</tr>
</c:if>
</c:forEach>
</table>
<!-- <table id="done"> -->
</div>
</div>
<!-- <div class="context"> -->
</div>
<!-- <div class="all"> -->
main.jsp에서 AJAX를 통하여 값을 조회하여 화면에 출력할 것이다.
<script>
$(function(){
buttonEvent();
function buttonEvent(){
$("button").click(function(){
//클릭 했을때 필드 값을 수정 : 이벤트를 발생시킨 $(this) 해당 태그의 아이디와 상태값(type)
var type=$(this).attr("data-type");
var id=$(this).attr("data-id");
$.ajax({
url:"updateTodo",
data:{
type: type,
id: id
},
type:"post",
success:function(serverData){ // 즉 업데이트를 요청했을때 매퍼를 통하여 값을 조회한 후에 다시 값을 실어서 serverData 매개변수 쪽으로 넘어온다.
$("#todo").html("<tr><th>TODO</th></tr>");
$("#doing").html("<tr><th>DOING</th></tr>");
$("#done").html("<tr><th>DONE</th></tr>");
for(var i=0;i<serverData.length;i++){
var str="";
if(serverData[i].type=='TODO'){
str+='<tr id="'+serverData[i].id+'">';
str+='<td class="todoUpdate"><b>'+serverData[i].title+'</b><br /> 등록날짜:'+serverData[i].regdate+', '+serverData[i].name+', 우선순위'+serverData[i].sequence+'';
str+='<button data-id="'+serverData[i].id+'" data-type="'+serverData[i].type+'">☞</button>';
str+='</td>';
str+='</tr>';
$("#todo").append(str);
}else if(serverData[i].type=='DOING'){
str+='<tr id="'+serverData[i].id+'">';
str+='<td class="todoUpdate"><b>'+serverData[i].title+'</b><br /> 등록날짜:'+serverData[i].regdate+', '+serverData[i].name+', 우선순위'+serverData[i].sequence+'';
str+='<button data-id="'+serverData[i].id+'" data-type="'+serverData[i].type+'">☞</button>';
str+='</td>';
str+='</tr>';
$("#doing").append(str);
}else{//DONE
str+='<tr id="'+serverData[i].id+'">';
str+='<td class="todoUpdate"><b>'+serverData[i].title+'</b><br /> 등록날짜:'+serverData[i].regdate+', '+serverData[i].name+', 우선순위'+serverData[i].sequence+'';
str+='<button data-id="'+serverData[i].id+'" data-type="'+serverData[i].type+'">☞</button>';
str+='</td>';
str+='</tr>';
$("#done").append(str);
}
} // for() END
buttonEvent(); // 클릭시 마다 버튼이 새롭게 만들어지기 때문에 이벤트를 다시 부여한다.
} // success:function(){} END
}); // $.ajax({}) END
}); // $("button").click() END
} // function buttonEvent(){} END
});
</script>
$(function(){
buttonEvent();
function buttonEvent(){
$("button").click(function(){
첫번째 선언한 이벤트 는 뒤에가서 설명할 것이다.
butoonEvent() 함수를 만드는데 이 함수는 button이 클릭 될때 실행 될것이다.
type과 id라는 변수에 $(this)가 사용되었고 이 this에 attr 을 통하여 속성을 선택
this => 실행 된 버튼 중에 data-id, data-type 이라는 속성을 가진 태그를 의미한다.
메인 페이지 중
<button data-id="${todo.id}" data-type="${todo.type}">></button>
이 태그의 값을 의미한다.
$.ajax({
url:"updateTodo",
data:{
type: type,
id: id
},
type:"post",
$.ajax 시작
보내는 url => updateTodo
보내는 data : type파라미터명으로 type, id파라미터명으로 id, 전송 방식은 post방식으로 값을 전송.
success:function(serverData){
$("#todo").html("<tr><th>TODO</th></tr>");
$("#doing").html("<tr><th>DOING</th></tr>");
$("#done").html("<tr><th>DONE</th></tr>");
값이 성공적으로 전송이 되면 콜백함수 설정하는데 이때 들어오는 매개변수 명을 serverData로 설정했다.
테이블 태그를 보면 속성 id값으로 todo,doing,done이 설정 되어있다.
만약 값이 정상적으로 넘어가서 success 메서드가 실행된다면 선언된 html 태그를 추가한다.
아직 버튼이 실행되지 않아서 테이블의 제목 부분이 TODO : 해야 할 일 이러한 형태로 되어있는데 버튼이 클릭되어 이벤트가 발생하게 된다면,
위에서 설정한 제목으로 바뀌게 된다.
ajax형식을 다시 보자
updateTodo 라는 url로 보내지는데
TodoController를 살펴보면
//TODO AJAX
@RequestMapping(value="/updateTodo",method = RequestMethod.POST)
public @ResponseBody List<TodoDTO> updateTodo(TodoDTO dto){ //@ResponseBody 때문에 요청한 쪽으로 데이터가 다시 나간다.(즉, main.jsp url 부분의 updateTodo 쪽 으로 그대로 다시 반환 s)
//데이터 처리 작업 필요
repo.updateTodo(dto);
return repo.selectTodo();
}
@RequestMapping(value="/updateTodo",method = RequestMethod.POST)
updateTodo라는 값으로 요청이 들어오는데 이때 post방식으로 요청이 들어오면 해당 메서드가 실행되게된다.
반환 타입 : @ResponseBody
@ResponseBody 때문에 요청한 쪽으로 데이터가 다시 나간다.(즉, main.jsp url 부분의 updateTodo 쪽으로 그대로 다시 반환 ) => 이 값을 main.jsp 에서 ajax 성공시게 serverData 라는 매개 변수에 저장하게 되어있다.
SQL 문을 저장 해놓은 todoMapper.xml을 확인 해보면
<select id="selectTodo" resultType="Todo">
SELECT
id, title, name, sequence, type, regdate
FROM
todoList
ORDER BY regdate DESC
</select>
<update id="updateTodo" parameterType="Todo">
UPDATE todoList SET
<if test="type=='TODO'">
type='DOING'
</if>
<if test="type=='DOING'">
type='DONE'
</if>
WHERE id = #{id}
</update>
controller에서 updateTodo 메서드를 실행한 후에
main.jsp로 selectTodo 메서드 값을 보내게 된다(위에서 말한것처럼 @ResponseBody에 의하여)
*** mybatis에서 SQL문을 사용하는 방법은 2가지가 있다.
1번째 : SqlSession 객체가 가지고 있는 insert, delete, update, selectOne, selectList ~~ 내장되어있는 메서드를 활용하거나
2번째 : 위의 방법 처럼 개발자가 직접 Mapper 인터페이스를 구현하여 구현한 메서드를 등록 시켜 사용하는 방법.
이때 todoMapper.xml은 반드시 각각의 태그에 유일한 값으로 id를 지정하는데 이 id값은 반드시 인터페이스의 메서드 명과 동일해야한다!!!!
또한 xml문서는 반드시 인터페이스를 등록 하는것 !!!
<mapper namespace="com.jdh.spring.repository.TodoMapper">
TodoMapper라는 인터페이스를 만들었었고 그 인터페이스를 가지고 올 수 있게 경로를 설정 했다.
for(var i=0;i<serverData.length;i++){
var str="";
if(serverData[i].type=='TODO'){
str+='<tr id="'+serverData[i].id+'">';
str+='<td class="todoUpdate"><b>'+serverData[i].title+'</b><br /> 등록날짜:'+serverData[i].regdate+', '+serverData[i].name+', 우선순위'+serverData[i].sequence+'';
str+='<button data-id="'+serverData[i].id+'" data-type="'+serverData[i].type+'">☞</button>';
str+='</td>';
str+='</tr>';
$("#todo").append(str);
TodoController를 통하여 조회한 값을 serverData에 반환 받았다.
반복문을 돌리는데 문자열을 저장받을 변수 str ( 빈 값으로 만들어준 후)
str에 serverData가 가지고 있는 각각의 데이터를 저장 받고
id=todo를 가진 태그에 (현재 table에 속성이 선언되어있다.)
jQuery의 append() 메서드를 통하여 str값을 추가 시킨다.
이로써 첫번째 if문이 끝났고 나머지 조건문도 같은 방식이다.
else if (serverData[i].type=='DOING'){
전달받은 type의 값이 DOING이면 이쪽을
else {//DONE
TODO와 DOING이 아닌것은 DONE임으로 마지막 조거문을 실행하게 된다.
마찬가지로 $("#doing").append(str); // $("#done").append(str); 의 값을 추가하게 된다.
이로써 반복문이 끝나면
buttonEvent(); 버튼 이벤트 다시 부여한다. (마지막 부분)
해당 값들을 저장 했고, 버튼에 이벤트를 부여 함으로써 test2 메모장의 버튼은 클릭 이벤트가 생성 되었다.
초기 화면이다
test2라는 제목을 가진 메모장의 버튼을 누를 것이다.
그러면 위의 ajax를 통하여 TODO였던 type이 updateTodo 메서드를 통하여 DOING으로 바뀌면서 옆으로 이동할 것 이다.
버튼을 눌렀고 데이터 이동이 일어났고, 저 메모장은 새로 생기게 된것이다.
우리가 처음 함수를 실행시킬때 첫번째에 buttonEvent 함수를 호출 하고 시작했다.
저 부분을 로드 할때 저 버튼에 대한 이벤트가 없으므로 부여하기 위하여
main.jsp 에서 c:forEach 부분에서 도대체 저 ${todoList} 이부분!!
main.jsp는 프로젝트 실행시 가장 먼저 보여지게 되는 페이지이다.
그렇기 때문에 초기에 HomeController 에서 home -> main으로 수정을 했었다.
마찬가지로 초기에 값을 조회하여 todoList라는 변수에 담아 페이지 전환이 이루어졌을때 값을 넘겨줘야한다.
즉, HomeController에 조회하는 메서드를 실행시켜 todoList에 담아 전달하면 된다.
HomeController.java
@Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
@Autowired
TodoRepository repo;
/**
* Simply selects the home view to render by returning its name.
*/
@RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
model.addAttribute("todoList", repo.selectTodo());
return "main";
}
}
이 프로젝트에서 DAO역할을 하는 TodoRepository 객체를 생성해 준다. (@Autowried에 의해 객체가 주입된다.)
return "main"을 하기전에 해당 값을 조회하여 값을 담아 전달 하면 끝!!
이 프로젝트의 경우 완벽한 CRUD가 이루어지지 않는다. (삭제 기능이 없다..)
단순히 ajax가 spring에서 어떠한 방식으로 동작하는 지 확인하고
이부분에서 mybatis는 어떠한 구조로 작동하는지를 학습하기 위한 프로젝트였다.
나중에 활용할 수 있을꺼 같아 Github에 저장해 두었다.
'Learn > KH정보교육원' 카테고리의 다른 글
[KH 정보교육원 당산] 77일 ( Spring Boot - IntelliJ IDEA / MariaDB) (0) | 2021.07.07 |
---|---|
[KH정보교육원 당산] 76일( JPA ) (0) | 2021.07.05 |
[KH정보교육원 당산] 연습문제9 (인터페이스 구현) (0) | 2021.07.01 |
[KH정보교육원 당산] 74일 (Spring흐름 및 Ajax를 활용한 To-Do list) (0) | 2021.06.30 |
[KH정보교육원 당산] 73일( Spring - Mybatis ) (0) | 2021.06.29 |