記事詳細
- 投稿日
- 2026年09月09日09時52分
-
タイトル
-
ASP.NET Core MVC の Create ビューで、親 <select> に「新規項目」を追加できるようにし、その場で子 <select> にも新規項目を追加し、DB に保存する ということで、親<select asp-for="PaymentTypeId" class="form-control" asp-items="@(ViewData["PaymentTypeId"] as SelectList)">、子<select asp-for="PaymentMethodId" class="form-control" asp-items="@(ViewData["PaymentMethodId"] as SelectList)"> そして、親テーブル名「PaymentTypes」子テーブル名「PaymentMethod」です。
- 内容
-
了解です。
では、先ほどの ASP.NET Core MVC の Create ビューで親<select>と子<select>に新規項目を追加し、その場で DB 保存する 実装例を、
より実用的に改良したバージョンを提示します。今回は Bootstrap モーダルフォーム を使って入力する形に変更し、
バリデーションや UX を改善しています。1. モデル例(変更なし)
Csharp
public class PaymentType { public int Id { get; set; } public string Name { get; set; } } public class PaymentMethod { public int Id { get; set; } public string Name { get; set; } public int PaymentTypeId { get; set; } }2. コントローラー例(CSRF 対策付き)
Csharp
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Rendering; using YourApp.Data; using YourApp.Models; public class PaymentsController : Controller { private readonly ApplicationDbContext _context; public PaymentsController(ApplicationDbContext context) { _context = context; } public IActionResult Create() { ViewData["PaymentTypeId"] = new SelectList(_context.PaymentTypes, "Id", "Name"); ViewData["PaymentMethodId"] = new SelectList(Enumerable.Empty<PaymentMethod>(), "Id", "Name"); return View(); } [HttpPost] [ValidateAntiForgeryToken] public IActionResult AddPaymentType(string name) { if (string.IsNullOrWhiteSpace(name)) return BadRequest("Name is required"); var type = new PaymentType { Name = name.Trim() }; _context.PaymentTypes.Add(type); _context.SaveChanges(); return Json(new { id = type.Id, name = type.Name }); } [HttpPost] [ValidateAntiForgeryToken] public IActionResult AddPaymentMethod(string name, int paymentTypeId) { if (string.IsNullOrWhiteSpace(name)) return BadRequest("Name is required"); var method = new PaymentMethod { Name = name.Trim(), PaymentTypeId = paymentTypeId }; _context.PaymentMethods.Add(method); _context.SaveChanges(); return Json(new { id = method.Id, name = method.Name }); } [HttpGet] public IActionResult GetPaymentMethods(int paymentTypeId) { var methods = _context.PaymentMethods .Where(m => m.PaymentTypeId == paymentTypeId) .Select(m => new { id = m.Id, name = m.Name }) .ToList(); return Json(methods); } }3. Create.cshtml(モーダル対応版)
Razor
@model YourApp.Models.Payment <div class="form-group"> <label asp-for="PaymentTypeId"></label> <select asp-for="PaymentTypeId" class="form-control" asp-items="@(ViewData["PaymentTypeId"] as SelectList)" id="paymentTypeSelect"></select> <button type="button" class="btn btn-sm btn-primary mt-1" data-bs-toggle="modal" data-bs-target="#addPaymentTypeModal">+ 新規追加</button> </div> <div class="form-group"> <label asp-for="PaymentMethodId"></label> <select asp-for="PaymentMethodId" class="form-control" asp-items="@(ViewData["PaymentMethodId"] as SelectList)" id="paymentMethodSelect"></select> <button type="button" class="btn btn-sm btn-primary mt-1" data-bs-toggle="modal" data-bs-target="#addPaymentMethodModal">+ 新規追加</button> </div> <!-- 親追加モーダル --> <div class="modal fade" id="addPaymentTypeModal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"><h5 class="modal-title">支払種別の追加</h5></div> <div class="modal-body"> <input type="text" id="newPaymentTypeName" class="form-control" placeholder="支払種別名"> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button> <button type="button" class="btn btn-primary" id="savePaymentTypeBtn">保存</button> </div> </div> </div> </div> <!-- 子追加モーダル --> <div class="modal fade" id="addPaymentMethodModal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"><h5 class="modal-title">支払方法の追加</h5></div> <div class="modal-body"> <input type="text" id="newPaymentMethodName" class="form-control" placeholder="支払方法名"> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">キャンセル</button> <button type="button" class="btn btn-primary" id="savePaymentMethodBtn">保存</button> </div> </div> </div> </div> @section Scripts { <script> $(function () { // 親選択時に子リスト更新 $('#paymentTypeSelect').change(function () { var typeId = $(this).val(); $.getJSON('/Payments/GetPaymentMethods', { paymentTypeId: typeId }, function (data) { var $child = $('#paymentMethodSelect').empty(); $.each(data, function (i, item) { $child.append($('<option>', { value: item.id, text: item.name })); }); }); }); // 親保存 $('#savePaymentTypeBtn').click(function () { var name = $('#newPaymentTypeName').val().trim(); if (!name) { alert('名前を入力してください'); return; } $.post('/Payments/AddPaymentType', { name: name, __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() }, function (data) { $('#paymentTypeSelect').append($('<option>', { value: data.id, text: data.name, selected: true })).trigger('change'); $('#addPaymentTypeModal').modal('hide'); $('#newPaymentTypeName').val(''); }); }); // 子保存 $('#savePaymentMethodBtn').click(function () { var typeId = $('#paymentTypeSelect').val(); if (!typeId) { alert('先に支払種別を選択してください'); return; } var name = $('#newPaymentMethodName').val().trim(); if (!name) { alert('名前を入力してください'); return; } $.post('/Payments/AddPaymentMethod', { name: name, paymentTypeId: typeId, __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() }, function (data) { $('#paymentMethodSelect').append($('<option>', { value: data.id, text: data.name, selected: true })); $('#addPaymentMethodModal').modal('hide'); $('#newPaymentMethodName').val(''); }); }); }); </script> }Powered by Froala Editor
-
添付画像
-
画像はありません
- Genreのカテゴリ-名
- Views