⓪ 前書き(疲れを感じている人は読んでみてね)
この記事は、気楽に読み返せる技術ナレッジをベースになるべくやわらかい雰囲気を目指して作成しています
そのため、「昨日の自分」さんと「今日の自分」さんに登場してもらい、技術課題の解決方法を記します
読んだ後、新しい技術を使いこなせているエンジニアとして少しだけもやもやを解消した、「今日の自分」になれますようにという願いも込めて

① 本題:やりたかったこと
(「昨日の自分」さんは↓ を実装したいと考えています ☁☁)
Springで
・CRUD操作を、
・画面遷移せず、
・モーダル上のみで完結させたい
② 壁
(「昨日の自分さん」は今回、以下の疑問点で手が止まりました ☁☁)
①そもそもモーダルってどう作ればいいの?
②モーダルだけでなく、オーバーレイがセットで必須らしいけどどうして!?
③表示/非表示はどうやって切り替えるの?
③ 結論
(「今日の自分」さんは解決をこう結論づけました 🏔🏔☀)
①モーダルは、CSSで作成
・モーダルの正体は、以下の3層構造
<最前面>
「モーダル本体(ウィンドウ)」
「オーバーレイ(背景)」 ←ユーザー操作をブロック!
「元の表示画面」
<最背面>
②オーバーレイの役割は、
モーダル本体を表示中、モーダルの責務である「モーダル表示中は元の表示画面である背景画面は操作できない」を果たすため(最背面の「元の画面」が操作できないよう)に、
・「元の画面」の代わりにクリックなどのユーザー操作を受け止めブロックすること
つまり、モーダル責務(モーダル表示中は背景画面が操作できない)を果たす役割があるため必須
③表示/非表示は、JavaScriptで作成
・「追加」ボタンを押したときに、モーダルウィンドウを表示!
・「閉じる」ボタンを押したときに、モーダルウィンドウを非表示!
を担当
④実装方法
(「昨日の自分さん」は「今日の自分さん」と一緒に↓ で課題解決しました ★★🚀)
■完成イメージ
■成果物
以下2点
①モーダル本体
・CSS、HTML
②モーダルの表示/非表示
・JavaScript、HTML
■実装手順
①モーダル本体
1. モーダルウィンドウ作成
CSSで作ります
.bookModal {
display: none;
position: fixed;
top: 20%;
left: 50%;
transform: translateX(-50%);
width: 400px;
padding: 20px;
background-color: white;
border: 1px solid #333;
z-index: 1000;
}
2. オーバーレイ作成
CSSで作ります
.modalOverlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.3);
z-index: 999;
}
3. HTMLにモーダル本体(モーダルウィンドウ・オーバーレイ)実装
・divタグにclass=”bookModal”とclass=”modalOverlay”を付与
→モーダル完成!
<!-- 本追加モーダル -->
<button type="button" id="openBookModal">本追加</button>
<div id="modalOverlay" class="modalOverlay"></div>
<div id="bookModal" class="bookModal"
th:style="${isBookModalOpen} ? 'display:block;' : 'display:none;'">
<h2>本追加モーダル</h2>
< p>手動入力</p>
<button type="button" id="closeBookModal">閉じる</button>
</div>
4. 入力フォーム・送信ボタン作成
・class=”bookModal”をもつdivタグ直下に、formタグを用いて記述
→フォーム完成!
<!-- 本追加モーダル -->
<button type="button">本追加</button>
<div class="modalOverlay"></div>
<div class="bookModal"
th:style="${isBookModalOpen} ? 'display:block;' : 'display:none;'">
<h2>本追加モーダル</h2>
<p>手動入力</p>
<form th:action="@{/projects/{projectId}/books(projectId=${projectId})}"
th:object="${bookCreateForm}"
method="post">
<label for="bookTitle">題名</label>
<input type="text" id="bookTitle" th:field="*{bookTitle}"></br>
<div th:if="${#fields.hasErrors('bookTitle')}" th:errors="*{bookTitle}" style="color:red;"></div> <button type="submit">追加</button></br>
</form>
<button type="button">閉じる</button>
</div>
②モーダルの表示/非表示
1. JavaScriptがHTMLのモーダル・ボタンを取得&操作できるようする
・HTMLで、モーダルウィンドウに当たるdivタグ(class=”openBookModal”付与)内に、
→id=”openBookModal”を付与
<div id="bookModal" class="bookModal">
・HTMLで、オーバーレイに当たるdivタグ(class=”modalOverlay”付与)内に、
→id=”modalOverlay”を付与
<div id="modalOverlay" class="modalOverlay"></div>
・モーダル表示用ボタンにid=””付与(任意の名前でOK)
<button type="button" id="openBookModal">本追加</button>
・モーダル非表示用ボタンにid=””付与(任意の名前でOK)
<button type="button" id="closeBookModal">閉じる</button>
・JavaScriptで、scriptタグを記述して、
「const 定数名 = document.getElementById(‘id名’)」を用いて上記4つのdivタグを要素取得する
※bodyタグの最下部に記述すること
<script>
// 本追加モーダル制御
const openBookModalButton = document.getElementById('openBookModal');
const closeBookModalButton = document.getElementById('closeBookModal');
const bookModal = document.getElementById('bookModal');
const modalOverlay = document.getElementById('modalOverlay');
</script>
</body>
2. 表示/非表示機能の実装
・addEventListenerメソッド
「addEventListener( 'クリックした時' () => 表示/非表示 )」を用いる
・表示する時は、display='block';
・非表示にする時は、display='none';
<script>
// 本追加モーダル制御
const openBookModalButton = document.getElementById('openBookModal');
const closeBookModalButton = document.getElementById('closeBookModal');
const bookModal = document.getElementById('bookModal');
const modalOverlay = document.getElementById('modalOverlay');
openBookModalButton.addEventListener('click', () => {
bookModal.style.display = 'block';
modalOverlay.style.display = 'block';
});
closeBookModalButton.addEventListener('click', () => {
bookModal.style.display = 'none';
modalOverlay.style.display = 'none';
});
</script>
</body>
⑤ まとめ
(「今日の自分」さんからの教え 🌸🍡🌕)
・モーダル本体は「CSS」
・モーダル操作(表示/非表示)は「JavaScript」で作成する
・オーバーレイの必要性は、モーダルウィンドウだけではできない「元の画面」操作をブロックすることにある
★特別な仕組みではなく、既存技術の組み合わせでモーダルは実現できるんです!★
⑥ 今後やりたいこと
Ajaxとの使い分け
モーダルのバリデーション制御
部分更新(画面リロードなし)

