なるほど、状況を整理するとこうですね。
- ASP.NET Core MVC の CreateView において
- 親
<select> → PaymentTypeId(テーブル: PaymentTypes) - 子
<select> → PaymentMethodId(テーブル: PaymentMethod)
- 親の
<select> に 新規項目を追加できるようにしたい(追加後は即座に選択状態にする) - 子の
<select> も同様に 新規項目を追加できるようにしたい - 両方とも DB保存が必要
- 親子関係は
PaymentType 1 : N PaymentMethod
これは典型的な 親子ドロップダウン + Ajax 新規追加 のパターンです。
以下のような構成で実装できます。
1. モデル定義
// 親
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. コントローラ
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
@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