반응형

printMessage.html

  • 이 페이지는 내용을 출력하기 위한 페이지가 아닌 javascript를 통해 메세지를 출력해주고, 바로 다음 페이지로 이동시켜주는 페이지
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>게시판</title>
</head>
<body>
  <script th:inline="javascript">
    window.onload = function () {
      if([[${message}]] != null) {
        alert([[${message}]])
      }
      window.location.href = [[${nextUrl}]]
    }
  </script>
</body>
</html>

header.html

  • 화면 상단의 nav-bar와 Bootstrap, css 등을 import 해주는 페이지
  • 모든 페이지에 같은 nav-bar가 들어가기 때문에 한번 만들어 놓고 thymeleaf의 fragment를 통해 다른 페이지에서는 <div th:replace="fragments/header.html :: header ('admin')"/> 이런 식으로 불러서 사용하기만 하면 됨
  • thymeleaf-extras-springsecurity5 라이브러리를 설치하고, html 태그에 xmlns:sec="http://www.thymeleaf.org/extras/spring-security"를 추가해주면 sec:authorize="isAuthenticated()", sec:authorize="hasAuthority('ADMIN')" 와 같이 인증, 인가를 쉽게 할 수 있음
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head th:fragment="head">
    <meta charset="utf-8">
    <title>게시판</title>
    <!-- Bootstrap 5.2.3 Version -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">

    <!-- My CSS -->
    <link rel="stylesheet" href="/css/custom.css">

    <!-- JQuery -->
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

</head>

<body>

<div th:fragment="header (pageName)">
    <!-- Bootstrap 5.2.3 Version -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>

    <nav class="navbar navbar-expand-lg" style="background-color: limegreen; margin-bottom: 60px;">
        <div class="container-fluid">
            <a class="navbar-brand" href="/">Basic Board</a>
            <div class="collapse navbar-collapse" id="navbarNavDropdown">
                <!--<ul class="navbar-nav">-->
                <ul class="navbar-nav">
                    <li class="nav-item">
                        <a th:if="${pageName == 'home'}" class="nav-link active" aria-current="page" href="/">Home</a>
                        <a th:unless="${pageName == 'home'}" class="nav-link" aria-current="page" href="/">Home</a>
                    </li>
                    <li class="nav-item">
                        <a th:if="${pageName == 'greeting'}" class="nav-link active" aria-current="page" href="/boards/greeting">가입인사</a>
                        <a th:unless="${pageName == 'greeting'}" class="nav-link" aria-current="page" href="/boards/greeting">가입인사</a>
                    </li>
                    <li class="nav-item">
                        <a th:if="${pageName == 'free'}" class="nav-link active" aria-current="page" href="/boards/free">자유게시판</a>
                        <a th:unless="${pageName == 'free'}" class="nav-link" aria-current="page" href="/boards/free">자유게시판</a>
                    </li>
                    <li class="nav-item">
                        <a th:if="${pageName == 'gold'}" class="nav-link active" aria-current="page" href="/boards/gold">골드게시판</a>
                        <a th:unless="${pageName == 'gold'}" class="nav-link" aria-current="page" href="/boards/gold">골드게시판</a>
                    </li>
                </ul>
            </div>
            <div class="justify-content-between" id="navbarNav" style="padding: 5px 30px">

                <!-- 로그인 안 했을때 -->
                <ul class="navbar-nav" sec:authorize="isAnonymous()">
                    <li class="nav-item">
                        <button class="btn nav-btn" onclick="location.href = '/users/login'">로그인</button>
                    </li>
                    <li class="nav-item">
                        <button class="btn nav-btn" onclick="location.href = '/users/join'">회원가입</button>
                    </li>
                </ul>

                <!-- 로그인 했을때 -->
                <ul class="navbar-nav" sec:authorize="isAuthenticated()">
                    <li class="nav-item" sec:authorize="hasAuthority('ADMIN')">
                        <button class="btn nav-btn" onclick="location.href = '/users/admin'" style="width: fit-content">관리자 페이지</button>
                    </li>
                    <li class="nav-item">
                        <button class="btn nav-btn" onclick="location.href = '/users/myPage/board'">마이페이지</button>
                    </li>
                    <li class="nav-item">
                        <button class="btn nav-btn" onclick="location.href = '/users/logout'">로그아웃</button>
                    </li>
                </ul>

            </div>
        </div>
    </nav>
</div>

</body>

확인 메세지 출력

function clickDelete() {
    if (confirm("해당 글을 삭제 하시겠습니까?") == true) {
        location.href = "/boards/" + [[${category}]] + "/" + [[${boardDto.id}]] + "/delete";
    }
}
  • boards/detail.html에서 위와 같은 코드가 있음
  • 이 코드는 버튼을 눌렀을 때, 바로 GET 요청을 보내지 않고 확인 메세지를 출력해 줌
  • 확인 메세지에서 확인 버튼을 눌러야 if 문 안의 내용이 실행됨

페이지 기능 구현

window.onload = function () {
    let nowPage = [[${boards.getNumber()}]] + 1;    // 현재 페이지
    let totalPage = [[${boards.getTotalPages()}]];  // 전체 페이지 수

    let firstPage;  // 화면에 출력될 첫 페이지
    for (let i = nowPage ; i >= 1 ; i --) {
        if(i % 5 == 1) {
            firstPage = i;
            break;
        }
    }

    let lastPage;   // 화면에 출력될 마지막 페이지
    let nextButton; // 다음 버튼 출력 여부
    if (firstPage + 4 >= totalPage) {
        lastPage = totalPage;
        nextButton = false;
    } else {
        lastPage = firstPage + 4;
        nextButton = true;
    }

    // HTML 생성
    let pageHtml = "";
    pageHtml += "<li><a class='page-link' href='" + makeUrl(1) +  "'>&laquo;</a></li>";
    if (firstPage != 1) {
        pageHtml += "<li><a class='page-link' href='" + makeUrl(firstPage - 1) +  "'>&lsaquo;</a></li>";
    }

    for (let i = firstPage; i <= lastPage; i++) {
        if (i == nowPage) {
            pageHtml += "<li class='page-item active'><a class= 'page-link'>" + i + "</a></li>";
        } else {
            pageHtml += "<li class='page-item'><a class= 'page-link' href='" + makeUrl(i) + "'>" + i + "</a></li>";
        }
    }

    if (nextButton) {
        pageHtml += "<li><a class='page-link' href='" + makeUrl(lastPage + 1) +  "'>&rsaquo;</a></li>";
    }
    pageHtml += "<li><a class='page-link' href='" + makeUrl(totalPage) +  "'>&raquo;</a></li>";

    $("#paging-ul").html(pageHtml);
}

function makeUrl(page) {
    let category = [[${category}]];
    let url = "/boards/" + category + "?page=" + page;

    // 검색 했으면 다음 URL에도 추가
    let sortType = [[${boardSearchRequest.sortType}]];
    let searchType = [[${boardSearchRequest.searchType}]];
    let keyword = [[${boardSearchRequest.keyword}]];

    if (sortType != null) {
        url += "&sortType=" + sortType;
    }
    if (searchType != null) {
        url += "&searchType=" + searchType + "&keyword=" + keyword;
    }

    return url;
}
  • boards/list.html에서 위와 같은 코드가 있음
  • 이 코드는 해당 html 파일이 open 될 때 페이지 버튼을 만드는 코드
  • 이 사이트에서는 1 ~ 5, ^ ~ 10과 같이 5개의 페이지 단위로 버튼을 생성함
  • Model로 넘어온 값들을 Thymeleaf 문법을 사용해 받고, 현재 페이지와 전체 페이지를 통해 첫번째 페이지, 마지막 페이지를 계산하고, 버튼을 생성함
  • 또한, 정렬, 검색을 했다면 sortType, searchType, keyword가 넘어오게 되는데, 이 값들을 url에 추가해줌으로써, 검색, 정렬 후 페이지 이동을 했을 때, 검색, 정렬 결과가 유지될 수 있게 해줌

파일 입력

<form class="offset-3 col-6 form-group" th:object="${boardCreateRequest}" th:method="post"
        th:action="|@{/boards/{category} (category = ${category})}|" enctype="multipart/form-data">
    <div>
        <label th:for="title">제목 : </label>
        <input type="text" th:field="*{title}" style="width: 50%">
    </div>
    <br/>

    <div>
        <label th:for="body">내용 : </label>
        <textarea rows="10" style="width: 100%;" th:field="*{body}"/>
    </div>
    <br/>
    <div>
        <label th:for="uploadImage">이미지 첨부 : </label>
        <input type="file" th:field="*{uploadImage}" style="width: 50%">
    </div>
    <br/>
    <div align="center">
        <button class="btn post-btn" type="submit">등록</button>
    </div>
</form>
반응형

↓ 클릭시 이동

복사했습니다!