SpringBootアプリをBootstrapを使用できるように設定を行う方法を解説しています

SpringBoot

はじめに

学習時間管理アプリ#7です。

こちらの記事ではBootstrapを使用してレイアウトを調整しています。WEBアプリケーションのレイアウトでお困りな方は、少し役に立てる情報があるかもしれません。

ハンズオンで作成されている方は前回の記事をお読みでない方は下記からどうぞ!

SpringBootで年月毎に表示できるようにJPQLを作成し、セレクトボックスで実装する方法を解説します

BootStrapを導入する

  • BootStrapを導入するには<head>タグの中に以下のコードを埋め込みます。
  • </body>の上に以下のコードを埋め込みます。
HTML
<head>
	<!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
	<!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
studyTimeList.htmlを編集する

埋め込んだコードの全文は以下です。

studyTimeList.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>学習時間一覧</title>
	<!-- Bootstrap -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
	<h1>学習時間一覧</h1>
	<a th:href="@{/studytime/new}">学習を開始する</a>
	
	<form action="/studytime" method="get">
		<select name="year">
			<th:block th:each="year : ${years}">
				<option th:value="${year}" th:text="${year}" th:selected="${year == currentYear}"></option>
			</th:block>
		</select>
		<select name="month">
			<th:block th:each="month : ${months}">
				<option th:value="${month}" th:text="${month}" th:selected="${month == currentMonth}"></option>
			</th:block>
		</select>
		
		<button type="submit">表示</button>
	</form>
	
	<p>当月の学習時間: <sapn th:text="${currentMonthTotal}"></sapn></p>
	<p>前月の学習時間: <sapn th:text="${lastMonthTotal}"></sapn></p>
	<table>
		<tr>
			<th>日付</th>
			<th>開始時間</th>
			<th>終了時間</th>
			<th>操作</th>
		</tr>
		<tr th:each="studyTime : ${studyTimes}">
			<td th:text="${studyTime.startTime.format(T(java.time.format.DateTimeFormatter).ofPattern('yyyy/MM/dd'))}"></td>
			<td th:text="${studyTime.startTime.format(T(java.time.format.DateTimeFormatter).ofPattern('HH時mm分'))}"></td>
			<td th:text="${studyTime.endTime != null ? studyTime.endTime.format(T(java.time.format.DateTimeFormatter).ofPattern('HH時mm分')): ''}"></td>
			<td>
				<a th:href="@{/studytime/{id}/edit(id=${studyTime.studyTimesId})}">編集</a>
				<form th:action="@{/studytime/{id}/delete(id=${studyTime.studyTimesId})}" method="post" style="display: inline;">
					<button type="submit">削除</button>
				</form>
			</td>
		</tr>
	</table>
	<!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body>
</html>
studyTimeForm.htmlを編集する
studyTimeForm.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>学習時間の入力</title>
	<!-- Bootstrap -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
	<script>
		function updateTime() {
			// Ajaxでサーバーから現在の時刻を取得
			fetch('/studytime/current-time')
			.then(response => response.text())
			.then(data => {
				document.getElementById('currentTime').textContent = data; // 取得した時刻を表示
			})
			.catch(error => console.error('Error:', error));
		}
		
		// 1秒ごとにupdateTime関数を呼び出す
		setInterval(updateTime, 1000);
	</script>
	
</head>
<body>
	<h1>学習時間の入力</h1>
	<div>
		<p th:text="${date}"></p>
		<p th:text="${currentDayOfWeek}"></p>
		<p id="currentTime" th:text="${time}"></p>
	</div>
	<form th:action="@{/studytime}" method="post">
		<button type="submit" name="action" value="start" th:disabled="${isLearningActive}">学習開始</button>
		<button type="submit" name="action" value="end" th:disabled="${!isLearningActive}">学習終了</button>
	</form>
	
	<a href="/studytime">戻る</a>
	<!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body>
</html>
edit.htmlを編集する
edit.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>学習時間の編集</title>
	<!-- Bootstrap -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
	<h1>学習時間の編集</h1>
	<form th:action="@{/studytime/{id}(id=${studyTimeObject.studyTimesId})}" th:object="${studyTimeObject}" method="post">
		<label>開始時間:</label>
		<input type="datetime-local" th:field="*{startTime}" required />
		<label>終了時間:</label>
		<input type="datetime-local" th:field="*{endTime}" required />
		<button type="submit">変更</button>
	</form>
	
	<a href="/studytime">戻る</a>
	<!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body>
</html>

レイアウトの調整をする

今回編集ページに関しては、時間の都合でレイアウトは未実装です。一覧ページと学習時間入力ページに関しては軽く整えました。

以下がコードです。

studyTimeList.htmlを編集する
studyTimeList.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>学習時間一覧</title>
	<!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
<body>
	<div class="container">
		<div class="row mb-3 mt-5">
			<div class="col-6"><h3 class="text-left">学習時間一覧</h3></div>
			<div class="col-6">
				<div class="text-left mb-3 border-bottom pb-2">表示年月選択</div>
				<div class="row mb-3">
				    <form action="/studytime" method="get" class="d-flex">
				        <div class="col-3 me-3">
				            <select name="year" class="form-select">
				                <th:block th:each="year : ${years}">
				                    <option th:value="${year}" th:text="${year}" th:selected="${year == currentYear}"></option>
				                </th:block>
				            </select>
				        </div>
				        <div class="col-3 me-3">
				            <select name="month" class="form-select">
				                <th:block th:each="month : ${months}">
				                    <option th:value="${month}" th:text="${month}" th:selected="${month == currentMonth}"></option>
				                </th:block>
				            </select>
				        </div>
				        <div class="col-3 ml-3">
				            <button type="submit" class="btn btn-primary">表示</button>
				        </div>
				    </form>
				</div>
			</div>
		</div>
		<div class="row">
			<div class="col-6">
				<a th:href="@{/studytime/new}">学習時間を管理</a>
			</div>
			<div class="col-6">
				<div class="row">
					<div class="col-6"><p>当月: <sapn th:text="${currentMonthTotal}"></sapn>時間</p></div>
					<div class="col-6"><p>前月: <sapn th:text="${lastMonthTotal}"></sapn>時間</p></div>
				</div>
			</div>
		</div>
		<div class="row">
			<table class="table table-striped table-hover">
			    <thead class="table-primary">
			        <tr>
			            <th>日付</th>
			            <th>開始時間</th>
			            <th>終了時間</th>
			            <th>操作</th>
			        </tr>
			    </thead>
			    <tbody>
			        <tr th:each="studyTime : ${studyTimes}">
			            <td th:text="${studyTime.startTime.format(T(java.time.format.DateTimeFormatter).ofPattern('yyyy/MM/dd'))}"></td>
			            <td th:text="${studyTime.startTime.format(T(java.time.format.DateTimeFormatter).ofPattern('HH時mm分'))}"></td>
			            <td th:text="${studyTime.endTime != null ? studyTime.endTime.format(T(java.time.format.DateTimeFormatter).ofPattern('HH時mm分')): ''}"></td>
			            <td>
			                <a th:href="@{/studytime/{id}/edit(id=${studyTime.studyTimesId})}" class="btn btn-warning btn-sm me-3">編集</a>
			                <form th:action="@{/studytime/{id}/delete(id=${studyTime.studyTimesId})}" method="post" style="display: inline;">
			                    <button type="submit" class="btn btn-danger btn-sm">削除</button>
			                </form>
			            </td>
			        </tr>
			    </tbody>
			</table>
		</div>
	</div>
	<!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body>
</html>
studyTimeForm.htmlを編集する
studyTimeForm.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta charset="UTF-8">
	<title>学習時間の入力</title>
	<!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
	<script>
		function updateTime() {
			// Ajaxでサーバーから現在の時刻を取得
			fetch('/studytime/current-time')
			.then(response => response.text())
			.then(data => {
				document.getElementById('currentTime').textContent = data; // 取得した時刻を表示
			})
			.catch(error => console.error('Error:', error));
		}
		
		// 1秒ごとにupdateTime関数を呼び出す
		setInterval(updateTime, 1000);
	</script>
	
</head>
<body>
	<div class="container mt-5">
	    <h3 class="text-center mb-4">学習時間の打刻</h3>    
	    <div class="row mb-4">
	        <div class="col text-center">
	            <div class="d-flex justify-content-center mb-2">
	                <span class="me-2" th:text="${date}"></span>
	                <span th:text="${currentDayOfWeek}"></span>
	            </div>
	            <h1 id="currentTime" class="display-1" th:text="${time}"></h1>
	        </div>
	    </div>
	    <div class="row">
	        <div class="col text-center">
	            <form th:action="@{/studytime}" method="post" class="mb-3">
	                <button type="submit" name="action" value="start" class="btn btn-success me-2" th:disabled="${isLearningActive}">学習開始</button>
	                <button type="submit" name="action" value="end" class="btn btn-danger" th:disabled="${!isLearningActive}">学習終了</button>
	            </form>
	            <a href="/studytime" class="btn btn-link">戻る</a>
	        </div>
	    </div>
	</div>
	<!-- Bootstrap -->
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-geWF76RCwLtnZ8qwWowPQNguL3RmwHVBC9FhGdlKrxdiJJigb/j/68SIy3Te4Bkz" crossorigin="anonymous"></script>
</body>
</html>

それでは、ブラウザで確認してみましょう!!

おわりに

#7まで読んで頂いた方ありがとうございます。ハンズオンで作成された方はお疲れさまでした!大変だったと思いますが、少しでもスキルが身についたのではないでしょうか?筆者自身もエラーに何度も直面しては調べての繰り返しでしたので、とても勉強になりました。

お読みいただきありがとうございました。

コメント