記事詳細


投稿日
2026年09月08日16時59分
タイトル

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保存が必要です。

内容

なるほど、状況を整理するとこうですね。

  • ASP.NET Core MVC の CreateView において
    • 親 <select> → PaymentTypeId(テーブル: PaymentTypes
    • 子 <select> → PaymentMethodId(テーブル: PaymentMethod
  • 親の <select> に 新規項目を追加できるようにしたい(追加後は即座に選択状態にする)
  • 子の <select> も同様に 新規項目を追加できるようにしたい
  • 両方とも DB保存が必要
  • 親子関係は PaymentType 1 : N PaymentMethod

これは典型的な 親子ドロップダウン + Ajax 新規追加 のパターンです。
以下のような構成で実装できます。

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; } // Create GET public IActionResult Create() { ViewData["PaymentTypeId"] = new SelectList(_context.PaymentTypes, "Id", "Name"); ViewData["PaymentMethodId"] = new SelectList(Enumerable.Empty<SelectListItem>()); return View(); } // Ajax: 親追加 [HttpPost] public IActionResult AddPaymentType(string name) { if (string.IsNullOrWhiteSpace(name)) return BadRequest("Name is required"); var type = new PaymentType { Name = name }; _context.PaymentTypes.Add(type); _context.SaveChanges(); return Json(new { id = type.Id, name = type.Name }); } // Ajax: 子追加 [HttpPost] public IActionResult AddPaymentMethod(int paymentTypeId, string name) { if (string.IsNullOrWhiteSpace(name)) return BadRequest("Name is required"); var method = new PaymentMethod { Name = name, PaymentTypeId = paymentTypeId }; _context.PaymentMethods.Add(method); _context.SaveChanges(); return Json(new { id = method.Id, name = method.Name }); } // Ajax: 子リスト取得 [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" id="btnAddType">+</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" id="btnAddMethod">+</button> </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 })); }); }); }); // 親追加 $('#btnAddType').click(function () { var name = prompt("新しい支払タイプ名を入力してください:"); if (!name) return; $.post('/Payments/AddPaymentType', { name: name }, function (data) { $('#PaymentTypeId').append($('<option>', { value: data.id, text: data.name, selected: true })); $('#PaymentTypeId').trigger('change'); // 子リスト更新 }); }); // 子追加 $('#btnAddMethod').click(function () { var typeId = $('#PaymentTypeId').val(); if (!typeId) { alert("先に支払タイプを選択してください"); return; } var name = prompt("新しい支払方法名を入力してください:"); if (!name) return; $.post('/Payments/AddPaymentMethod', { paymentTypeId: typeId, name: name }, function (data) { $('#PaymentMethodId').append($('<option>', { value: data.id, text: data.name, selected: true })); }); }); }); </script> }

4. 実装のポイント

  • Ajaxで即DB保存 → 追加後に <select> に append して selected にする
  • 親変更時に子リストを再取得(GetPaymentMethods
  • 入力は prompt で簡易実装していますが、モーダルフォームにすればUIが改善します
  • バリデーションはサーバー側でも必須(空文字や重複チェックなど)

✅ この方法なら、

  • 親 <select> に新規項目追加 → 即選択状態
  • 子 <select> に新規項目追加 → 即選択状態
  • 両方ともDBに保存され、親子関係も維持
    が可能です。

もし希望があれば、このコードを Bootstrapモーダル対応版 にして、
入力フォームで追加できるように改良したサンプルも作れますが、
それも作りますか?
そうすれば UX がかなり向上します。

Powered by Froala Editor

添付画像

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