detail.html
<button id="updateBtn" th:data-todo-no="${todo.todoNo}">수정</button>
th:data-* 에 할 일 번호 실어서 보내주기
detail.js
const updateBtn = document.querySelector("#updateBtn");
updateBtn.addEventListener("click", e => {
// data-todo-no 에 실어둔 todoNo 얻어오기
const todoNo = e.target.dataset.todoNo;
location.href = `/todo/update?todoNo=${todoNo}`;
});
클릭했을 때 받은 할 일 번호를 쿼리스트링으로 controller 에 보내줌
Controller
@GetMapping("update")
public String todoUpdate(@RequestParam("todoNo") int todoNo,
Model model) {
// 상세 조회 서비스 호출하면 수정화면에 출력할 이전 내용을 쓸 거임
// todoNo 를 전달하면 상세 조회해주는 서비스 재활용
Todo todo = service.todoDetail(todoNo);
model.addAttribute("todo", todo);
// forward 시켜줄 거임
return "todo/update";
templates/todo/update.html 파일 만들어서 안에 내용 작성
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title th:text="|${todo.todoNo}번 할 일 수정|"></title>
</head>
<body>
<h1 th:text="|${todo.todoNo}번 할 일 수정|"></h1>
<hr>
<form action="/todo/update" method="post">
<div>
<!-- 이전에 작성되어있었던 내용 가져와서 보여주기 위해서 thymeleaf 사용 -->
제목 : <input type="text" name="todoTitle" th:value="${todo.todoTitle}">
<!-- thymeleaf 사용시 html 에서 사용할 수 있는 속성들 앞에 th 만 붙이면 다 쓸 수 있음 -->
</div>
<div>
<textarea name="todoContent"
cols="50" rows="5" placeholder="상세 내용"
th:text="${todo.todoContent}"></textarea>
</div>
textArea 태그는 value 라는 속성이 없기 때문에 th:text 로 내용 보여주기
어떤 글에 대한 수정인지 요청 보낼 때 알려줘야함
GET 요청이었으면 queryString 에 값 담아서 보내줬겠지만 post 요청이라서 queryString 사용할 수 없음
할 일 번호를 숨겨둠 : 요청 시 name=value 같이 보내줌
<input type="hidden" name="todoNo" th:value="${param.todoNo}">
<!-- todo.todoNo 로 보내도 되지만 지금 parameter에 todoNo 가 실려있어서 param.todoNo으로 보냄 -->
<button>수정하기</button>
</form>
<th:block th:replace="~{common/footer}"></th:block>
</body>
</html>

위에서 수정하기 누를 때 form 태그에 요청 주소가 /todo/update 이고 method는 post 요청
TodoController
위에서 todoUpdate method 와는 매개변수, mapping 방법이 달라서 같은 이름의 method 사용 가능
오버로딩 적용 매개변수 타입, 개수 다르면 오버로딩
/** 할 일 수정
* @param todo : 커맨드 객체 (전달 받은 파라미터가 자동으로 DTO의 필드에 세팅된 객체)
* @param ra
* @return
*/
@PostMapping("update")
public String todoUpdate(Todo todo, RedirectAttributes ra) {
// ModelAttribute 사용해서 가져온 거임
// redirect 해줄 거라서 RedirectAttributes 얻어옴
// 수정 서비스 호출 (update 할 거)
int result = service.todoUpdate(todo);
ServiceImpl
@Override
public int todoUpdate(Todo todo) {
return mapper.todoUpdate(todo);
}
TodoMapper
/** 할 일 수정
* @param todo
* @return result
*/
int todoUpdate(Todo todo);
todo-mapper.xml
<!-- 할 일 수정 -->
<!-- 파라미터가 DTO인 경우 : #{필드명}, ${필드명} -->
<!-- 파라미터가 Map인 경우 : #{key}, ${key} -->
<update id="todoUpdate" parameterType="Todo">
UPDATE TB_TODO SET
TODO_TITLE = #{todoTitle},
TODO_CONTENT = #{todoContent}
WHERE TODO_NO = #{todoNo}
</update>
Controller
String path = "redirect:";
String message = null;
if(result > 0) {
// 업데이트 성공시
// 상세 조회로 리다이렉트
path += "/todo/detail?todoNo=" + todo.getTodoNo();
message = "수정 성공";
} else {
// 다시 수정 화면으로 리다이렉트
path += "/todo/update?todoNo=" + todo.getTodoNo();
message = "수정 실패";
}
ra.addFlashAttribute("message", message);
return path;
조회한 값에 따라 path 를 다르게 저장해둬서 return path; 구문만 작성해주면 됨