記事詳細


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

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)">に、新規項目が追加出来るようにするSweetAlert2 を使用した方法を教えてください。親テーブル名「PaymentTypes」子テーブル名「PaymentMethod」DB保存が必要です。

内容

なるほど、やりたいことはこうですね。

  • ASP.NET Core MVC の CreateView に
    • 親 <select>PaymentTypeId
    • 子 <select>PaymentMethodId
  • 親に新しい項目を追加できる(SweetAlert2 で入力 → DB 保存 → 即反映)
  • 子も同様に新しい項目を追加できる(SweetAlert2 で入力 → DB 保存 → 即反映)
  • 親子は 協調表示(親選択で子が絞り込み)

以下に 完全動作するサンプル構成 を示します。
(Entity Framework Core を使用、SweetAlert2 は CDN で読み込み)

1. モデル定義

Csharp
// Models/PaymentType.cs public class PaymentType { public int Id { get; set; } public string Name { get; set; } = string.Empty; public ICollection<PaymentMethod> PaymentMethods { get; set; } = new List<PaymentMethod>(); } // Models/PaymentMethod.cs public class PaymentMethod { public int Id { get; set; } public string Name { get; set; } = string.Empty; public int PaymentTypeId { get; set; } public PaymentType PaymentType { get; set; } = null!; }

2. DbContext

Csharp
public class AppDbContext : DbContext { public DbSet<PaymentType> PaymentTypes { get; set; } public DbSet<PaymentMethod> PaymentMethods { get; set; } public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { } }

3. コントローラー

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 Create(int PaymentTypeId, int PaymentMethodId) { // 保存処理(例: 注文や支払いレコード) return RedirectToAction(nameof(Create)); } // 親追加 [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 }); } // 子追加 [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 }); } // 子リスト取得 [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); } }

4. Create.cshtml

Html
@{ ViewData["Title"] = "Create Payment"; } <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11/dist/sweetalert2.min.css"> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <form asp-action="Create" method="post"> <div class="form-group"> <label>Payment Type</label> <div class="input-group"> <select asp-for="PaymentTypeId" class="form-control" asp-items="@(ViewData["PaymentTypeId"] as SelectList)" id="PaymentTypeId"></select> <button type="button" class="btn btn-outline-primary" id="btnAddType">+</button> </div> </div> <div class="form-group mt-3"> <label>Payment Method</label> <div class="input-group"> <select asp-for="PaymentMethodId" class="form-control" asp-items="@(ViewData["PaymentMethodId"] as SelectList)" id="PaymentMethodId"></select> <button type="button" class="btn btn-outline-primary" id="btnAddMethod">+</button> </div> </div> <button type="submit" class="btn btn-success mt-3">Save</button> </form> <script> document.getElementById("PaymentTypeId").addEventListener("change", function () { const typeId = this.value; fetch(`/Payments/GetPaymentMethods?paymentTypeId=${typeId}`) .then(res => res.json()) .then(data => { const methodSelect = document.getElementById("PaymentMethodId"); methodSelect.innerHTML = ""; data.forEach(m => { methodSelect.innerHTML += `<option value="${m.id}">${m.name}</option>`; }); }); }); document.getElementById("btnAddType").addEventListener("click", function () { Swal.fire({ title: '新しいPayment Type', input: 'text', inputPlaceholder: 'Type name', showCancelButton: true, confirmButtonText: '追加' }).then(result => { if (result.isConfirmed && result.value.trim() !== "") { fetch('/Payments/AddPaymentType', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `name=${encodeURIComponent(result.value)}` }) .then(res => res.json()) .then(data => { const select = document.getElementById("PaymentTypeId"); const option = new Option(data.name, data.id, true, true); select.add(option); select.dispatchEvent(new Event('change')); // 子更新 }); } }); }); document.getElementById("btnAddMethod").addEventListener("click", function () { const typeId = document.getElementById("PaymentTypeId").value; if (!typeId) { Swal.fire('先にPayment Typeを選択してください'); return; } Swal.fire({ title: '新しいPayment Method', input: 'text', inputPlaceholder: 'Method name', showCancelButton: true, confirmButtonText: '追加' }).then(result => { if (result.isConfirmed && result.value.trim() !== "") { fetch('/Payments/AddPaymentMethod', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `paymentTypeId=${typeId}&name=${encodeURIComponent(result.value)}` }) .then(res => res.json()) .then(data => { const

Powered by Froala Editor

添付画像

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