reactかはてまたvue.jsか、と苦闘を続けているが、どうもよくない。reactにしてもvue.jsにしても最初はよかったのかもしれないが、バージョンが上がるにつれて、どうも自分の世界に全てをひきこもうとしているのが見え見えで、なんか使いづらいのだ。
ということで他を探すということにしてみた。
Alpine.jsね。
https://alpinejs.dev/
早速サンプルソース行ってみよう。
まず、親画面ですね。
index.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>モーダルウィンドウの例</title>
<link rel="stylesheet" href="styles.css">
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head>
<body x-data="app()">
<div x-data="{ open: false }">
<button @click="showModal = true">モーダルを開く1</button>
<p>選択結果:<span x-text="result"></span></p>
<div x-show="showModal" class="modal" @click.away="open = false">
<?php include ("fetch_content.php"); ?>
</div>
<div x-show="showModalSub" class="modal">
<?php include ("fetch_content_sub.php"); ?>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
ボタンをクリックでモーダルを開く、ということで、ボタンとそのモーダル一つ目と二つ目を用意している。モーダルの中身はphpから読み込む設定で、ここではincludeを使っているが、別にここは普通にテンプレートでよい。
で、モーダルの中身であるfetch_content.phpは、
<div class="modal-content">
<span @click="showModal = false" class="close">×</span>
<div>
<div>
<form>
<label for="name">名前:</label>
<input type="text" id="name" name="name" x-model="name">
<button type="button" @click="search()">検索</button>
</form>
</div>
<div x-html="searchResults"></div>
</div>
</div>
こんな感じ。モーダルを閉じる×印と、検索フォーム、結果表示部分で構成されている。
検索ボタンをクリックでsearch()関数に渡しているが、ここはphpのresult.phpを実行して結果をsearchResultsに書き込む想定だ。
result.php
<table>
<tbody>
<tr>
<th>ID</th>
<th>社名</th>
<th>日付</th>
</tr>
<tr @click="selectRow(1)">
<td>1</td>
<td>アイワ</td>
<td>2024-05-30</td>
</tr>
<tr @click="selectRow(2)">
<td>2</td>
<td>ソニー</td>
<td>2024-05-31</td>
</tr>
<tr @click="selectRow(3)">
<td>3</td>
<td>松下電器</td>
<td>2024-05-31</td>
</tr>
</tbody>
</table>
で、さらにこの結果表の行クリックselectRow()で次のモーダルを開き、また、そこで検索し、その結果行をクリックで、選択したIDを親画面に表示させようと、そういう構成である。
二つ目のモーダル
fetch_content_sub.php
<div x-show="showModalSub" class="modal">
<div class="modal-content">
<span @click="showModalSub = false" class="close">×</span>
<div>
<div>
<form>
<input type="hidden" id="company_id" name="company_id" x-model="companyId">
<label for="name">TEL:</label>
<input type="text" id="tel" name="tel" x-model="tel">
<button type="button" @click="searchSub()">検索</button>
</form>
</div>
<div x-html="searchSubResults"></div>
</div>
</div>
</div>
2つめモーダルで検索結果。
result_sub.php
<table>
<tbody>
<tr>
<th>ID</th>
<th>名前</th>
<th>日付</th>
</tr>
<tr @click="selectSubRow(1)">
<td>1</td>
<td>山田一郎</td>
<td>2024-05-30</td>
</tr>
<tr @click="selectSubRow(2)">
<td>2</td>
<td>田中花子</td>
<td>2024-05-31</td>
</tr>
</tbody>
</table>
ということで準備できたので、javascriptを書いていこう。
script.js
function app() {
return {
showModal: false,
showModalSub: false,
result: "",
companyId: "",
name: "",
tel: "",
searchResults: "",
searchSubResults: "",
async search() {
try {
const response = await fetch(`result.php?name=${this.name}`);
this.searchResults = await response.text();
} catch (error) {
console.error("Error fetching the content:", error);
}
},
selectRow(id) {
this.companyId = id;
this.showModalSub = true;
},
async searchSub() {
try {
const response = await fetch(
`result_sub.php?tel=${this.tel}&company_id=${this.companyId}`
);
this.searchSubResults = await response.text();
} catch (error) {
console.error("Error fetching the content:", error);
}
},
selectSubRow(id) {
this.showModalSub = false;
this.showModal = false;
this.result = id;
this.searchResults = "";
this.searchSubResults = "";
this.name = "";
this.tel = "";
},
};
}
おっつ。これはなかなかシンプルじゃない?
ちなみにcssはこんな感じで。
styles.css
/* モーダルのスタイル */
.modal {
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
overflow: auto;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.4);
padding-top: 60px;
}
.modal-content {
background-color: #fefefe;
margin: 5% auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
.close {
color: #aaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: black;
text-decoration: none;
cursor: pointer;
}
table {
width: 100%;
border-collapse: collapse;
}
th,
td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}