🏁 はじめに
前回(第6章:Bootstrapでデザインを整えてみる)では、UIをきれいに整えました。
今回はさらに一歩進んで、ページを再読み込みせずデータを更新する「非同期通信(AJAX)」 に挑戦します。
🎯 今回のゴール
「完了」ボタンを押すと、ページをリロードせずに状態を更新できるようにする
最終的な動き👇
✅ ボタンを押す → DB更新 → ページを再読み込みせず「完了!」と反映
🧩 Step 1:非同期通信とは?
通常、フォーム送信などはサーバーにリクエストを送るたびにページ全体が再読み込みされます。
非同期通信(AJAX)を使うと、JavaScript経由で一部データだけをサーバーとやり取りできます。
| 通信方式 | 特徴 |
|---|---|
| 同期通信(従来) | ページ全体を再読み込み |
| 非同期通信(AJAX) | 必要な部分だけ更新できる(ユーザー体験UP!) |
⚙️ Step 2:Todoモデルに完了フラグを追加
Models/Todo.cs に新しいプロパティを追加します。
public bool IsDone { get; set; } = false;
この変更をDBに反映させるため、マイグレーションを実行します。
Add-Migration AddIsDone
Update-Database
🧠 Step 3:ControllerにAPIメソッドを追加
TodosController に新しいアクションを追加します👇
[HttpPost]
public IActionResult ToggleDone(int id)
{
var todo = _context.Todos.Find(id);
if (todo == null) return NotFound();
todo.IsDone = !todo.IsDone;
_context.SaveChanges();
return Json(new { success = true, isDone = todo.IsDone });
}
ポイント:
-
Json()を返すことで、JavaScript側で扱いやすいデータ形式(JSON)にする -
isDoneを切り替えることで完了/未完を反転させる
🧾 Step 4:View(Index.cshtml)で非同期ボタンを実装
Views/Todos/Index.cshtml を以下のように変更します👇
@model IEnumerable<MyFirstAspNetApp.Models.Todo>
<h2 class="mb-3">Todo一覧</h2>
<table class="table table-striped table-bordered">
<thead class="table-dark">
<tr>
<th>ID</th>
<th>タイトル</th>
<th>状態</th>
<th>操作</th>
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr data-id="@item.Id">
<td>@item.Id</td>
<td>@item.Title</td>
<td class="status">@((item.IsDone) ? "完了" : "未完了")</td>
<td>
<button class="btn btn-sm btn-success toggle-btn">
@(item.IsDone ? "戻す" : "完了")
</button>
</td>
</tr>
}
</tbody>
</table>
@section Scripts {
<script>
document.querySelectorAll('.toggle-btn').forEach(btn => {
btn.addEventListener('click', async e => {
const row = e.target.closest('tr');
const id = row.dataset.id;
const res = await fetch('/Todos/ToggleDone', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'id=' + id
});
const data = await res.json();
if (data.success) {
const statusCell = row.querySelector('.status');
statusCell.textContent = data.isDone ? '完了' : '未完了';
e.target.textContent = data.isDone ? '戻す' : '完了';
}
});
});
</script>
}
💡 JavaScriptのポイント
| コード | 意味 |
|---|---|
fetch('/Todos/ToggleDone', { method: 'POST', ... }) |
Controllerに非同期POST送信 |
await res.json() |
Controllerの返り値(JSON)を受け取る |
statusCell.textContent = ... |
ページを再読み込みせずに文字を更新 |
▶ Step 5:実行してみよう!
-
/Todosを開く - 「完了」ボタンを押す
- 即座に「完了」表示に変わる!
- 再度押すと「未完了」に戻る
🎉 ページの再読み込みなしでDBの内容を更新できました!
✅ まとめ
| 学び | 内容 |
|---|---|
| fetch() | 非同期通信でサーバーとやり取り |
| ControllerのJson() | JSに返しやすいデータ形式 |
| ページの動的更新 | DOM操作で部分書き換え |
| UX向上 | ユーザー体験を大幅に改善 |
💬 学んでみて感じたこと
- ControllerとJavaScriptを連携させるとアプリが一気に「動く」ようになる
- ASP.NET MVCはサーバーサイド中心でもJSを簡単に統合できる
- fetch()の書き方を覚えれば、API連携の基礎も理解できる