記事詳細


投稿日
2026年09月08日17時02分
タイトル

Bootstrapモーダル ASP.NET Core MVC: CreateViewのform内の親階層の<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」DB保存が

内容

以下は、前回のサンプルを改良した Bootstrapモーダル対応版 の ASP.NET Core MVC 実装例です。
prompt を廃止し、モーダルフォームで新規項目を追加できるようにしています。
これにより UX が向上し、バリデーションや入力補助も行いやすくなります。

1. モデル

Csharp
public class PaymentType { public int Id { get; set; } public string Name { get; set; } public ICollection<PaymentMethod> PaymentMethods { get; set; } } public class PaymentMethod { public int Id { get; set; } public string Name { get; set; } public int PaymentTypeId { get; set; } public PaymentType PaymentType { get; set; } }

2. コントローラ

Csharp
public class PaymentsController : Controller { private readonly AppDbContext _context; public PaymentsController(AppDbContext context) { _context = context; } public IActionResult Create() { ViewData["PaymentTypeId"] = new SelectList(_context.PaymentTypes, "Id", "Name"); ViewData["PaymentMethodId"] = new SelectList(Enumerable.Empty<SelectListItem>()); return View(); } [HttpPost] 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] public IActionResult AddPaymentMethod(int paymentTypeId, string name) { 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

Cshtml
@model YourNamespace.Models.Payment <div class="form-group"> <label asp-for="PaymentTypeId"></label> <div class="input-group"> <select asp-for="PaymentTypeId" class="form-control" asp-items="@(ViewData["PaymentTypeId"] as SelectList)"></select> <button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#addTypeModal">+</button> </div> </div> <div class="form-group"> <label asp-for="PaymentMethodId"></label> <div class="input-group"> <select asp-for="PaymentMethodId" class="form-control" asp-items="@(ViewData["PaymentMethodId"] as SelectList)"></select> <button type="button" class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#addMethodModal">+</button> </div> </div> <!-- 親追加モーダル --> <div class="modal fade" id="addTypeModal" 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="newTypeName" 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="saveTypeBtn">保存</button> </div> </div> </div> </div> <!-- 子追加モーダル --> <div class="modal fade" id="addMethodModal" 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="newMethodName" 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="saveMethodBtn">保存</button> </div> </div> </div> </div> @section Scripts { <script> $(function () { // 親変更時に子リスト更新 $('#PaymentTypeId').change(function () { var typeId = $(this).val(); $.getJSON('/Payments/GetPaymentMethods', { paymentTypeId: typeId }, function (data) { var $method = $('#PaymentMethodId'); $method.empty(); $.each(data, function (i, item) { $method.append($('<option>', { value: item.id, text: item.name })); }); }); }); // 親保存 $('#saveTypeBtn').click(function () { var name = $('#newTypeName').val(); if (!name) return; $.post('/Payments/AddPaymentType', { name: name }, function (data) { $('#PaymentTypeId').append($('<option>', { value: data.id, text: data.name, selected: true })); $('#PaymentTypeId').trigger('change'); $('#addTypeModal').modal('hide'); $('#newTypeName').val(''); }); }); // 子保存 $('#saveMethodBtn').click(function () { var typeId = $('#PaymentTypeId').val(); if (!typeId) { alert("先に支払タイプを選択してください"); return; } var name = $('#newMethodName').val(); if (!name) return; $.post('/Payments/AddPaymentMethod', { paymentTypeId: typeId, name: name }, function (data) { $('#PaymentMethodId').append($('<option>', { value: data.id, text: data.name, selected: true })); $('#addMethodModal').modal('hide'); $('#newMethodName').val(''); }); }); }); </script> }

改良ポイント

  • Bootstrapモーダルで新規追加 → 入力UIが改善され、バリデーションも容易
  • Ajaxで即DB保存 → 保存後に <select> に反映し、選択状態に設定
  • 親変更時に子リストを自動更新
  • 入力欄は .val('') でリセットし、連続追加も可能

この構成なら、

  • 親・子どちらもモーダルから追加可能
  • 保存後

Powered by Froala Editor

添付画像

画像はありません
Genreのカテゴリ-名
Views
編集 | 記事一覧