읽기 전용으로 사용할 post.html을 생성해줍니다.
<!doctype html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head th:insert="~{fragments/common :: head('게시판')}">
<!-- Required meta tags -->
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
<!-- Bootstrap CSS -->
<link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css"
integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" rel="stylesheet">
<link href="starter-template.css" rel="stylesheet" th:href="@{/css/starter-template.css}">
<title>게시판</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top" th:insert="~{fragments/common :: menu('board')}">
<a class="navbar-brand" href="#">Spring Boot Tutorial</a>
<button aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation" class="navbar-toggler"
data-target="#navbarsExampleDefault" data-toggle="collapse" type="button">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">게시판</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<h2>게시판</h2>
<form th:object="${board}">
<input type="hidden" th:field="*{id}">
<div class="form-group">
<label for="title">제목</label>
<input type="text" class="form-control"
th:classappend="${#fields.hasErrors('title')} ? 'is-invalid'" id="title"
th:field="*{title}" readonly>
</div>
<div class="form-group">
<label for="content">내용</label>
<textarea class="form-control" id="content"
th:classappend="${#fields.hasErrors('content')} ? 'is-invalid'"
rows="10" th:field="*{content}" readonly></textarea>
</div>
<div class="text-right">
<a class="btn btn-primary" th:href="@{/board/list}">목록으로</a>
<a class="btn btn-primary" th:if="${board.title != null and (#authorization.expression('hasAuthority(''ROLE_ADMIN'')')
or (board.user != null and #authentication.name == board.user.username))}"
th:href="@{/board/form(id=*{id}, title=*{title}, content=*{content})}">수정</a>
<button th:if="${board.title != null and (#authorization.expression('hasAuthority(''ROLE_ADMIN'')') or (board.user != null and
#authentication.name == board.user.username))}" type="button" class="btn btn-primary" th:onclick="|deleteBoard(*{id})|">삭제</button>
</div>
</form>
</div>
</div>
<footer th:insert="~{fragments/common :: footer}"></footer>
<script>
function deleteBoard(id) {
//DELETE /api/boards/{id}
if(!confirm("게시글을 삭제하시겠습니까?")){
return;
}
$.ajax({
type: 'DELETE',
url: '/api/boards/' + id,
success: function(result) {
console.log('result', result);
alert('삭제됐습니다.');
//삭제 성공시 요청될 url
location.href = '/board/list';
}
});
}
</script>
</body>
</html>
제목과 내용 입력칸은 readonly를 사용하여 클릭도 할 수 없게 막아줍니다.
수정 버튼도 전에 form.thml에서 사용했던 것과 같이 게시글 작성자와 로그인한 사용자가 일치하거나 ADMIN 권한을 가지고 있는 경우에만 누를 수 있게 권한을 설정해줍니다.
수정을 누를 때
th:href="@{/board/form(id=*{id}, title=*{title}, content=*{content})}"
위 코드를 사용하여 기존 글의 id값, title, content를 가져옵니다.
BoardController.java 수정
post.html로 이동할 수 있게 GetMapping을 추가해줍니다.
@GetMapping("/post")
public String post(Model model, @RequestParam(required = false) Long id){
Board board = boardRepository.findById(id).orElse(null);
model.addAttribute("board", board);
return "board/post";
}
이제 list.html에서 게시글을 클릭 했을 경우 form.html이 아닌 post.html로 이동하게 해줍니다.
<tr th:each="board, i : ${boards}" th:onclick="'location.href=\'/board/post?id=' + ${board.id} + '\';'" style="cursor:pointer;">
ADMIN 권한을 가진 사용자 또는 자신의 작성글을 봤을 때 화면
자신의 글이 아닌 다른 사람의 글을 보는 일반 유저 화면
post.html을 수정해줍니다.
<div class="container">
<h2>게시판</h2>
<form th:object="${board}">
<input type="hidden" th:field="*{id}">
<div class="form-group">
<label for="title">제목</label>
<input type="text" class="form-control"
th:classappend="${#fields.hasErrors('title')} ? 'is-invalid'" id="title"
th:field="*{title}" readonly>
</div>
<div class="form-group">
<label for="content">내용</label>
<textarea class="form-control" id="content"
th:classappend="${#fields.hasErrors('content')} ? 'is-invalid'"
rows="10" th:field="*{content}" readonly></textarea>
</div>
<div class="text-right">
<a class="btn btn-primary" th:href="@{/board/list}">목록으로</a>
<a class="btn btn-primary" th:if="${board.title != null and (#authorization.expression('hasAuthority(''ROLE_ADMIN'')')
or (board.user != null and #authentication.name == board.user.username))}"
th:href="@{/board/form(id=*{id}, title=*{title}, content=*{content})}">수정</a>
<button th:if="${board.title != null and (#authorization.expression('hasAuthority(''ROLE_ADMIN'')') or (board.user != null and
#authentication.name == board.user.username))}" type="button" class="btn btn-primary" th:onclick="|deleteBoard(*{id})|">삭제</button>
</div>
</form>
</div>
<div style="float: right; padding-right: 50px; padding-top: 50px " >
<p>작성일: <span th:text="${#temporals.format(board.createdAt, 'yyyy:MM:dd')}"></span></p>
<p>작성시간: <span th:text="${#temporals.format(board.createdAt, 'HH:mm:ss')}"></span></p>
</div>
새로운 div를 만들어준 뒤 padding을 사용해 여백을 만들어줍니다.
post.html 목록 버튼 수정
<a class="btn btn-primary" onclick="history.back()">목록으로</a>
JavaScript의 history.back() 메소드는 브라우저의 이전 페이지로 이동하는 역할을 합니다.