Today
-
Yesterday
-
Total
-

ABOUT ME

-

  • Spring Boot (게시판) | Header, Footer 공통영역 레이아웃 설정
    ▼ Backend/└ 게시판 만들기 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

    board.zip
    0.21MB

     

    반응형

    댓글

Designed by Tistory.