✏️ 삭제 기능 구현
- 권한이 있는 클라이언트에 한해 삭제 기능 정상 작동
📍 Web 삭제 버튼 추가 - V1.
- 삭제는 수정과 달리 href 속성값을
javascript:void(0)
로 설정했다.
- javascprit 를 호출하는 코드이다.
- 삭제 버튼을 눌렀을 경우 “정말로 삭제하시겠습니까?” 와같은 확인 절차를 넣으려고 설정되었다.
th:data-uri
- 삭제를 실행할 URL 을 얻기 위한 로직
- javascript 코드가 시작되고 얻어낸 URL 을 매개변수로 사용하기위해 추가되었다.
delete
- 삭제 버튼이 눌리는 이벤트를 확인할 수 있도록 class 속성에 추가
- javascript
- 최 하단에 javascript 영역을 만들어 확인로직을 구현했다.
- 사용자가 확인을 누르면 data-uri 값으로 url 을 호출해 삭제가 완료된다.
- 취소를 누르면 아무일도 발생하지 않는다.
<a href="javascript:void(0);"
th:data-uri="@{|/question/delete/${question.id}|}"
class="delete btn btn-sm btn-outline-secondary"
sec:authorize="isAuthenticated()"
th:if="${question.author != null
and #authentication.getPrincipal().getUsername() == question.author.username}"
th:text="삭제"></a>
<script layout:fragment="script"
type="text/javascript">
const delete_elements = document.getElementsByClassName("delete");
Array.from(delete_elements).forEach(function (element) {
element.addEventListener('clic', function () {
if (confirm("정말로 삭제하시겠습니까?")) {
location.href = this.dataset.url;
};
});
});
</script>
</html>
📍 Web 삭제 버튼 추가 - V2.
- 자바스크립트 로직을 별도로 만들지 않고
onclick
만으로 동일한 효과를 만들어낼 수 있다.
onclick="return confirm(...)
- 버튼을 클릭할경우 괄호 안의 메시지가 팝업된다.
- 팝업 메시지에서 확인을 누를경우 로직이 실행되고,
취소를 누르면 실행되지 않는다.
<a onclick="return confirm('정말로 삭제하시겠습니까?');"
th:href="@{|/question/delete/${question.id}|}"
class="btn btn-sm btn-outline-secondary"
sec:authorize="isAuthenticated()"
th:if="${question.author != null
and #authentication.getPrincipal().getUsername() == question.author.username}"
th:text="삭제"></a>
📍 layout 계층 - javascript 레이아웃으로 추가
- body 의 최 하단부에 javascript 를 포함시킨다.
- 화면 랜더링이 완료되지 않은 상태로 javascript 가 실행되면 오류 또는 로딩 지연이 발생할 수 있다.
<!doctype html>
<html lang="ko" xmlns:layout="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" type="text/css" th:href="@{/bootstrap.min.css}">
<link rel="stylesheet" type="text/css" th:href="@{/style.css}">
<title>Hello, sbb!</title>
</head>
<body>
<nav th:replace="~{navbar :: navbarFragment}"></nav>
<th:block layout:fragment="content"></th:block>
<script th:src="@{/bootstrap.min.js}"></script>
<th:block layout:fragment="script"></th:block>
</body>
</html>
📍 Service 계층 - 객체 삭제 기능 추가
@Service
@RequiredArgsConstructor
public class QuestionService {
private final QuestionRepository questionRepository;
public void delete(Question question) {
questionRepository.delete(question);
}
}
📍 Controller 계층
@Controller
@RequestMapping("/question")
@RequiredArgsConstructor
public class QuestionController {
private final QuestionService questionService;
private final UserService userService;
@GetMapping("/delete/{id}")
@PreAuthorize("isAuthenticated()")
public String questionDelete(
@PathVariable Integer id,
Principal principal
) {
Question question = questionService.getQuestion(id);
if (!question.getAuthor().getUsername().equals(principal.getName()))
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "삭제 권한이 없습니다.");
questionService.delete(question);
return "redirect:/";
}
}