【食事内容管理Webアプリ】FullCalendarのボタン追加

前回までのあらすじ&今回の目標

前回は、データベースに登録されているデータを「FullCalendar」のカレンダーに表示できるように修正を行いました。

今後はそのデータベースにデータを登録する仕組みを追加していく予定です。

そして今回はその第一歩として、FullCalendarの「Toolbar」を用いて登録ボタンを追加し、データ登録用のモーダル画面を表示させることを目標に進めていきます。

FullCalendarのボタン追加方法

FullCalendarではヘッダ/フッタのツールバーにボタンを追加することができます。

追加するには下記のように「customButtons」と「headerToolbar/footerToolbar」のプロパティを記載する必要があります。

ボタン押下後の処理はclickプロパティに記載するようなので、7行目部分にモーダルの表示処理を実装すれば実現できそうです。

JavaScript (ボタン追加に必要なプロパティを記載)
let calendar = new FullCalendar.Calendar(calendarEl, {
  // customButtonsプロパティから自作ボタンを定義
	customButtons: {
		mybutton: {
		  // textはボタンには表示する文字列、clickにはボタン押下時の処理を記載
			text: "button",
			click: function() {...}
		}
	},
	headerToolbar: {
	  // 上記で定義したボタンを記載する
	  // ボタンは画面左、中央、右に出力可能でそれぞれleft(start)、center、right(end)で指定する
		right: 'mybutton',
		// ボタンは半角スペースで分けることで複数出力可能
		// today、prev,nextのようにFullCalendarが既に用意しているボタンもある
		center: 'today prev,next'
	}
});

実装

モーダル画面の作成

モーダル画面は別のファイルに書き出しました。実際に使用する際にはThymeleafのフラグメント式を使用してコンテンツを挿入するようにします。(3~12行目、14~51行目)

またアイコンは「Material Symbols」を使用して出力しています。

registration.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
  <head th:fragment="registration_head(links)">
	  <!--/* 当htmlのhead内容 */-->
    <meta charset='utf-8'/>
    <script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.14/index.global.min.js'></script>
    <script th:src="@{/js/editcalendar.js}"></script>
	  <link rel="stylesheet" th:href="@{/css\registration.css}">
	  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20,400,0,0" />
	  <!--/* 出力先のhead内容 */-->
	  <th:block th:replace="${links}" />
  </head>
  <body>
	<div th:fragment="registration-modal" id="modal" class="modal">
		<div class="modal-content">
			<label id="closer" class="closer">×</label>
			<div class="modal-content-title">
				<h2 class="title">メニューの新規登録</h2>
			</div>
			<form th:action="@{registration}">
				<div class="modal-content-row">
					<span class="material-symbols-outlined material-symbols-big-font">edit_calendar</span>
					<input id="eating-date" type="date">
				</div>
				<div class="modal-content-row">
					<div class="modal-content-icon"><span class="material-symbols-outlined material-symbols-big-font">chat_info</span></div>
					<div class="modal-content-input-area">
						<input id="meal-type-1" type="radio" name="meal-types">
						<label for="meal-type-1">朝食</label>
						<input id="meal-type-2" type="radio" name="meal-types">
						<label for="meal-type-2">昼食</label>
						<input id="meal-type-3" type="radio" name="meal-types">
						<label for="meal-type-3">夕食</label>
					</div>
				</div>
				<div class="modal-content-row">
					<div class="modal-content-icon"><span class="material-symbols-outlined material-symbols-big-font">restaurant</span></div>
					<div class="modal-content-input-area">
						<input type="text" placeholder="料理名を入力">
					</div>
				</div>
				<div class="modal-content-row">
					<span class="material-symbols-outlined material-symbols-big-font">description</span>
					<input type="text" placeholder="メモを入力">
				</div>
				<div class="submit">
					<input type="submit" value="上記内容で登録" class="submit-button">
				</div>
			</form>
		</div>
	</div>
  </body>
</html>

モーダル用のcssファイルは下記の通りです。見た目とモーダルを非表示する内容を記載しています。

registration.css
@charset "UTF-8";
.modal {
	position         : fixed;
	top              : 0;
	left             : 0;
	display          : none;
	z-index          : 1;
	width            : 100%;
	height           : 100%;
	align-items      : center;
	justify-content  : center;
	background-color : rgb(0 0 0 / 70%);
}

.modal-content {
	position         : absolute;
	width            : 45%;
	height           : 60%;
	background-color : #FEFEFE;
	border-radius    : 10px;
}

.modal-content .modal-content-title {
	border-radius    : 10px 10px 0 0;
	width            : 100%;
	background-color : #607080;
}

.modal-content .modal-content-title .title{
	width   : 90%;
	margin  : 0;
	padding : 10px;
	color   : #FEFEFE;
}

.material-symbols-outlined.material-symbols-big-font {
    font-size : 36px;
}

.modal-content .modal-content-row {
	display     : flex;
	align-items : center;
	padding     : 10px;
	column-gap  : 20px;
}

.closer {
	position        :absolute;
	top             : 10px;
	right           : 20px;
	font-size       : 24px;
	color           : #FEFEFE;
	text-decoration : none;
	cursor          : pointer;
}

.submit {
	text-align : center;
}

.submit-button {
  display       : inline-block;
  border-radius : 10px;
  font-size     : 12pt;
  text-align    : center;
  cursor        : pointer;
  padding       : 10px 48px;
  background    : lightslategray;
  color         : #fefefe;
  line-height   : 1em;
  border        : 2px solid lightslategray;
}

.submit-button:hover {
  color         : #f0f0f0;
  background    : #607080;
  border        : 2px solid #607080;
}

上記でモーダルの用意ができたため、あとは既存のhtmlにThymeleafのreplace属性を追加して挿入するだけになります。(3~8行目、11行目)

HTML
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="ja">
  <head th:replace="~{registration::registration_head(~{::link})}">
    <meta charset='utf-8' />
    <script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.14/index.global.min.js'></script>
	  <script th:src="@{/js/editcalendar.js}"></script>
	  <link th:href="@{/css/foodapp.css}"  rel="styleSheet" />
  </head>
  <body>
	<div id='calendar'></div>
	<div th:replace="~{registration::registration-modal}"></div>
	<script type="text/javascript" th:inline="javascript">
		document.addEventListener('DOMContentLoaded', initializeCalendar(/*[[${events}]]*/ null));
	</script>
  </body>
</html>
foodapp.css
@charset "UTF-8";
body {
  margin: 0;
}

JavaScriptの修正

修正点としては下記の通りです。今回の実装ではclickプロパティにモーダルを表示する処理を実装した関数を渡しています。

  • ボタン追加用のプロパティ追記(4~12行目)
  • カレンダー初期化時にモーダルの閉じるボタンの機能を追加(18~21行目)
  • モーダルの表示/非表示処理を追加(24~29行目、31~36行目)
JavaScript
function initializeCalendar(events) {
	let calendarEl = document.getElementById('calendar');
	let calendar = new FullCalendar.Calendar(calendarEl, {
		customButtons: {
			new: {
				text: "new",
				click: showRegistrationModal
			}
		},
		headerToolbar: {
			right: 'new today prev,next'
		},
		contentHeight: "auto",
		events
	});
	calendar.render();
	
	let closer = document.getElementById('closer');
	if (closer) {
	  closer.addEventListener('click', closeRegistrationModal);
	}
}

function showRegistrationModal() {
	let modal = document.getElementById("modal");
	if (modal) {
		modal.style.display = 'flex';
	}
}

function closeRegistrationModal() {
	let modal = document.getElementById('modal');
	if (modal) {
		modal.style.display = 'none';
	}
}

動作確認

まず初期表示ですが、画面右上に今回追加したnewボタンが出力されていますね。

○出力結果 (初期表示)
出力結果 (初期表示)

次にnewボタンを押下してみます。

○出力結果 (newボタン押下時)
出力結果 (newボタン押下時)

newボタンを押下すると今回作成したモーダルが無事表示されました。これであとはForm部分の修正とJava側に処理を追加すればメニューの登録ができるようになりそうですね!

今後の予定

今回はメニュー情報を入力するモーダル画面とその画面を表示させるボタンを「FullCalendar」を用いて実現しました。

次回はモーダルのForm部分の修正とJava側の実装を行って、データの登録処理を実装していきます。

今日の夕飯はチキン南蛮です。それではまた。。

コメント

タイトルとURLをコピーしました