▼ Backend/└ 게시판 만들기
Spring Boot (게시판) | Header, Footer 공통영역 레이아웃 설정
Valar
2021. 11. 1. 17:00
반응형
📌 구성환경
SpringBoot, Gradle, Thymeleaf, Jpa(JPQL), Jar, MariaDB
Thymeleaf Layout
Header, Footer와 같이 공통적으로 사용되는 코드를 화면마다 작성하지 않고 레이아웃 처리를 통해 공통 내용은 고정적으로 설정함으로써, 본래의 콘텐츠 내용에 집중할 수 있게 도와준다.
build.gradle
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
Gradle Refresh (적용)
프로젝트 우 클릭 → Gradle → Refresh Gradle Project
헤더 HTML
header.html (/src/main/resources/templates/fragments)
각 화면의 상단 부분에 공통적으로 들어갔던 영역을 작성한다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="headerFragment">
<head>
<title>Board List</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!--부트스트랩 css 추가-->
<link rel="stylesheet" href="/css/lib/bootstrap.min.css">
<!--jQuery 추가-->
<script src="/js/lib/jquery.min.js"></script>
<!--부트스트랩 script 추가-->
<script src="/js/lib/bootstrap.min.js"></script>
</head>
</th:block>
</html>
푸터 HTML
footer.html (/src/main/resources/templates/fragments)
각 화면의 하단 부분에 공통적으로 들어갔던 영역을 작성한다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<th:block th:fragment="footerFragment">
<div class="card mt-5">
<div class="card-body text-center">
<p class="card-text">
<small class="text-muted">Copyright © Venh.log Tistory Corp. All Rights Reserved.</small>
</p>
</div>
</div>
</th:block>
</html>
레이아웃 HTML
default_layout.html (/src/main/resources/templates/layout)
각 화면의 구성에 대한 설정을 한다.
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<th:block th:replace="fragments/header :: headerFragment"></th:block>
<body>
<th:block layout:fragment="content"></th:block>
</body>
<th:block th:replace="fragments/footer :: footerFragment"></th:block>
</html>
※ 본문 (실제 각 화면에 들어가는 내용)
1. html 태그에 레이아웃 설정을 해준다.
- xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
- layout:decorator="layout/default_layout"
2. th:block에 layout:fragment 설정을 한다.
- layout:fragment="content"
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout/default_layout">
<!-- layout Content -->
<th:block layout:fragment="content">
[본문 작성 영역..]
</th:block>
</html>
적용된 목록 HTML
list.html (/src/main/resources/templates/board)
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout/default_layout">
<!-- layout Content -->
<th:block layout:fragment="content">
<div id="wrapper">
<div class="container">
<form action="/board/list" id="frm" method="get">
<div class="col-md-12 mt-4">
<button type="button" class="btn btn-danger" onclick="fnDelete()">Delete</button>
<button type="button" class="btn btn-primary" onclick="javascript:location.href='/board/write'">Register</button>
<table class="table table-striped table-horizontal table-bordered mt-3">
<thead class="thead-strong">
<tr>
<th width="5%"><input type="checkbox" id="chkAll"></th>
<th width="10%">No.</th>
<th width="">Title.</th>
<th width="20%">Writer.</th>
<th width="10%">Views.</th>
<th width="20%">Reg Time.</th>
</tr>
</thead>
<tbody id="tbody">
<tr th:each="list,index : ${resultMap.list}" th:with="paging=${resultMap.paging}">
<td>
<input type="checkbox" name="deleteId" th:value="${list.id}">
</td>
<td>
<span th:text="${(resultMap.totalCnt - index.index) - (paging.pageNumber * paging.pageSize)}"></span>
</td>
<td>
<a th:href="@{./view(id=${list.id})}">
<span th:text="${list.title}"></span>
</a>
</td>
<td>
<span th:text="${list.registerId}"></span>
</td>
<td>
<span th:text="${list.readCnt}"></span>
</td>
<td>
<span th:text="${list.registerTime}"></span>
</td>
</tr>
</tbody>
</table>
<div class="row">
<div class="col">
<ul class="pagination">
<li class="page-item" th:each="index : ${#numbers.sequence(1, resultMap.totalPage)}" th:with="paging=${resultMap.paging}">
<a class="page-link" th:classappend="${paging.pageNumber == (index-1)} ? bg-primary : bg-secondary" th:href="@{./list(page=${index - 1},page=${paging.pageSize})}">
<span class="text-white" th:text="${index}"></span>
</a>
</li>
</ul>
</div>
</div>
</div>
</form>
</div>
</div>
<script th:inline="javascript">
// header checkbox event
$("#chkAll").click(function () {
if (this.checked) {
$("input[name='deleteId']").prop("checked", true);
} else {
$("input[name='deleteId']").prop("checked", false);
}
});
// body checkbox event
$("input[name='deleteId']").click(function () {
let delInpLen = $("input[name='deleteId']").length;
let delInpChkLen = $("input[name='deleteId']:checked").length;
if (delInpLen == delInpChkLen) {
$("#chkAll").prop("checked", true);
} else {
$("#chkAll").prop("checked", false);
}
});
function fnDelete() {
let delInpChkLen = $("input[name='deleteId']:checked").length;
if (delInpChkLen > 0) {
if (confirm("Do you want to delete it?")) {
let frm = $("#frm");
frm.attr("action", "/board/delete");
frm.attr("method", "post");
frm.submit();
}
} else {
alert("Not selected.");
}
}
</script>
</th:block>
</html>
테스트
※ thymeleaf:thymeleaf-layout-dialect의 최신 버전 적용 후 Layout 설정이 적용이 안될 때
layout:decorator="layout/default_layout"
↓
layout:decorate="~{layout/default_layout}"
GitHub
https://github.com/conf312/board_study.git
프로젝트 Import
압축을 풀고, 이클립스 import → General → Existing Projects into Workspace
반응형