[1] 아이템 삭제하기
각 아이템 마다 삭제 버튼이 달려있고, 그 삭제 버튼을 누르면 해당 아이템이 지워지는 걸 만들고자 한다.
(1) Controller 수정하기
삭제 기능을 만들어서 추가하면 된다.
package com.mysite.todo;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@RequiredArgsConstructor
@Controller
public class ToDoController {
private final ToDoService toDoService;
@RequestMapping("/todo")
public String list(Model model){
List<ToDoEntity> toDoEntityList = this.toDoService.getList();
model.addAttribute("toDoEntityList",toDoEntityList);
return "todolist";
}
@RequestMapping("/")
public String root(){
return "redirect:/todo";
}
@PostMapping("/todo/create")
public String todoCreate(@RequestParam String content){
this.toDoService.create(content);
return "redirect:/todo";
}
// 삭제 기능
@DeleteMapping("/todo/delete/{id}")
public String todoDelete(@PathVariable Integer id){
this.toDoService.delete(id);
return "redirect:/todo";
}
}
지우고자 하는 아이템의 아이디를 매개변수로 활용한다.
(2) Service 수정하기
데이터베이스에서 지우는 역할을 수행할 로직을 만들어준다.
package com.mysite.todo;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.CriteriaBuilder;
import javax.transaction.Transactional;
@RequiredArgsConstructor
@Service
public class ToDoService {
private final ToDoRepository toDoRepository;
public List<ToDoEntity> getList(){
return this.toDoRepository.findAll();
}
public void create(String content){
ToDoEntity toDoEntity = new ToDoEntity();
toDoEntity.setContent(content);
toDoEntity.setCompleted(false);
this.toDoRepository.save(toDoEntity);
}
@Transactional
public void delete(Integer id){
ToDoEntity toDoEntity = toDoRepository.findById(id)
.orElseThrow(()->new IllegalArgumentException("해당 아이템이 없습니다. id=" + id));
this.toDoRepository.delete(toDoEntity);
}
}
(3) html 수정하기
(i) 각 아이템마다 삭제 버튼 만들어주기
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>To Do List</title>
</head>
<body>
<h1>투두리스트</h1>
<form th:action="@{/todo/create}" method="post">
<input name="content" placeholder="오늘의 할 일을 적어보세요!"/>
<button>작성</button>
</form>
<table>
<thead>
<tr>
<th>번호</th>
<th>할 일</th>
<th>수행 여부</th>
<th>삭제</th>
</tr>
</thead>
<tbody>
<tr th:each="todoentity : ${toDoEntityList}" >
<td th:text="${todoentity.id}"></td>
<td th:text="${todoentity.content}"></td>
<td th:text="${todoentity.completed}"></td>
<td><button id="delete-btn">삭제</button></td>
</tr>
</tbody>
</table>
</body>
</html>
결과물은 다음과 같다.
(ii) 삭제 버튼에 기능 더하기
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>To Do List</title>
</head>
<body>
<h1>투두리스트</h1>
<form th:action="@{/todo/create}" method="post">
<input name="content" placeholder="오늘의 할 일을 적어보세요!"/>
<button>작성</button>
</form>
<table>
<thead>
<tr>
<th>번호</th>
<th>할 일</th>
<th>수행 여부</th>
<th>삭제</th>
</tr>
</thead>
<tbody>
<tr th:block th:each="todoentity : ${toDoEntityList}" >
<td th:text="${todoentity.id}"></td>
<td th:text="${todoentity.content}"></td>
<td th:text="${todoentity.completed}"></td>
<td><button id="delete-btn" th:onclick="deleteItem([[${todoentity.id}]])">삭제</button></td>
</tr>
</tbody>
</table>
</body>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
function deleteItem(id){
console.log(id)
const url = "/todo/delete/"+id
$.ajax({
type:'delete',
url:url,
contentType:'application/json; charset=utf-8'
}).done(function() {
alert('할 일이 삭제되었습니다.');
window.location.href = '/';
}).fail(function (error){
alert(JSON.stringify(error));
});
}
</script>
</html>
결과물은 다음과 같다.
OK를 누르면 제대로 삭제된 걸 확인할 수 있다.
+) 끝없는 삽질의 기록
(i) 왜 첫번째 값만 리턴되는 거야?
처음에 작성한 코드는 다음과 같다.
<td th:text="${todoentity.id}" id="id" th:value="${todoentity.id}"></td>
$('delete-btn').on('click', function (e) {
var id = $('id').attr('value');
const url = '/todo/delete/'+id
console.log(id)
$.ajax({
method: 'delete',
url: url,
contentType:'application/json; charset=utf-8'
}).done(function() {
alert('할 일이 삭제되었습니다.');
window.location.href = '/';
}).fail(function (error){
alert(JSON.stringify(error));
});
});
위처럼 작성했을 때는 값이 1번 값만 리턴되었다.
첫번째 버튼만 작동했으며, 어찌저찌 고쳐서 다른 버튼을 눌러도
첫번째 값만 삭제되는 그런 악몽 같은 결과를 마주했다.
그러다가 알게 된 사실이
var id = $('id').attr('value');
는 단순히 'td#id의 value값에 해당하는 것을 1개 찾는 것이라서
가장 첫번째 값을 가져온다는 점이였다.
그래서 이걸 각자의 id를 넣을 수 있도록 수정한게 (ii) 삭제 버튼에 기능더하기 이다.
각자의 값을 넣어주니 아주 잘 작동한다 👏
항상 잘보고 있습니다! 다름이 아니라 html 부분을 똑같이 해도 함수가 선언이 안되고, [[]] 부분이 오류가 뜨는데 적으신 코드처럼 해도 잘 작동하나요,,?