記事詳細
- 投稿日
- 2026年09月26日18時48分
-
タイトル
-
わかりました。 あなたのケースでは、ASP.NET Core MVC の <select> に「+項目を追加」を入れておき、選択されたら SweetAlert2 のモーダルフォームを表示 → AJAX で新しい項目を追加 → 成功後に <select> のリストを再読み込みする、という流れになります。 以下に 完全な実装例 を示します。
- 内容
-
了解しました。
前回のコードをベースに、意味のある差分を加えて改良版を提示します。
主な改良点は以下です:- SweetAlert2 モーダルに 画像プレビュー機能 を追加。
- 新規項目追加時に 重複チェック を行い、既存科目名と同じ場合はエラー表示。
- ファイル名の衝突を避けるため、アップロード時に GUID付きファイル名 に変更。
<select>の再読み込み時に 選択肢をアルファベット順に並び替え。
1. View(Create.cshtml)
Cshtml
@model YourNamespace.Models.Payment <form asp-action="Create" method="post" enctype="multipart/form-data"> <div class="form-group"> <label asp-for="SubjectNameId"></label> <select asp-for="SubjectNameId" class="form-control" asp-items="@(ViewData["SubjectNameId"] as SelectList)" id="SubjectNameId"> </select> </div> <button type="submit" class="btn btn-primary">登録</button> </form> @section Scripts { <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script> document.getElementById('SubjectNameId').addEventListener('change', function () { if (this.value === 'add') { Swal.fire({ title: '新しい科目を追加', html: ` <input id="courseName" class="swal2-input" placeholder="科目名"> <input type="file" id="imageFile" class="swal2-file" accept="image/*"> <img id="previewImg" style="max-width:100%;margin-top:10px;display:none;"> `, didOpen: () => { document.getElementById('imageFile').addEventListener('change', function () { const file = this.files[0]; if (file) { const reader = new FileReader(); reader.onload = e => { const img = document.getElementById('previewImg'); img.src = e.target.result; img.style.display = 'block'; }; reader.readAsDataURL(file); } }); }, focusConfirm: false, showCancelButton: true, confirmButtonText: '追加', preConfirm: () => { const courseName = document.getElementById('courseName').value.trim(); const imageFile = document.getElementById('imageFile').files[0]; if (!courseName) { Swal.showValidationMessage('科目名を入力してください'); return false; } const formData = new FormData(); formData.append('CourseName', courseName); if (imageFile) formData.append('ImageFile', imageFile); return fetch('/SubjectNames/AddSubjectName', { method: 'POST', body: formData }) .then(response => { if (!response.ok) throw new Error(response.statusText); return response.json(); }) .catch(error => { Swal.showValidationMessage(`リクエスト失敗: ${error}`); }); } }).then((result) => { if (result.isConfirmed) { Swal.fire('追加成功', '', 'success'); reloadSubjectList(result.value.id); } }); } }); function reloadSubjectList(selectedId) { fetch('/SubjectNames/GetSubjectList') .then(res => res.json()) .then(data => { // アルファベット順に並び替え data.sort((a, b) => a.courseName.localeCompare(b.courseName)); const select = document.getElementById('SubjectNameId'); select.innerHTML = ''; data.forEach(item => { const opt = document.createElement('option'); opt.value = item.subjectNameId; opt.textContent = item.courseName; select.appendChild(opt); }); const addOpt = document.createElement('option'); addOpt.value = 'add'; addOpt.textContent = '+項目を追加'; select.appendChild(addOpt); select.value = selectedId; }); } </script> }2. Controller(SubjectNamesController)
Csharp
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Http; using Microsoft.EntityFrameworkCore; using YourNamespace.Data; using YourNamespace.Models; using System.IO; using System.Threading.Tasks; using System; public class SubjectNamesController : Controller { private readonly ApplicationDbContext _context; private readonly IWebHostEnvironment _env; public SubjectNamesController(ApplicationDbContext context, IWebHostEnvironment env) { _context = context; _env = env; } [HttpPost] public async Task<IActionResult> AddSubjectName([FromForm] string CourseName, [FromForm] IFormFile ImageFile) { if (string.IsNullOrWhiteSpace(CourseName)) return BadRequest("CourseName is required"); // 重複チェック if (await _context.SubjectNames.AnyAsync(s => s.CourseName == CourseName)) return BadRequest("同じ科目名が既に存在します"); string imagePath = null; if (ImageFile != null && ImageFile.Length > 0) { var ext = Path.GetExtension(ImageFile.FileName); var fileName = $"{Guid.NewGuid()}{ext}"; var savePath = Path.Combine(_env.WebRootPath, "Images", fileName); using (var stream = new FileStream(savePath, FileMode.Create)) { await ImageFile.CopyToAsync(stream); } imagePath = "/Images/" + fileName; } var subject = new SubjectName { CourseName = CourseName, ImageUrl = imagePath }; _context.SubjectNames.Add(subject); await _context.SaveChangesAsync(); return Json(new { id = subject.SubjectNameId }); } [HttpGet] public async Task<IActionResult> GetSubjectList() { var list = await _context.SubjectNames .Select(s => new { subjectNameId = s.SubjectNameId, courseName = s.CourseName }) .ToListAsync(); return Json(list); } }3. Createアクション(PaymentController)
Csharp
public IActionResult Create() { var subjects = _context.SubjectNames.ToList(); subjects.Add(new SubjectName { SubjectNameId = 0, CourseName = "+項目を追加" }); ViewData["SubjectNameId"] = new SelectList(subjects, "SubjectNameId", "CourseName"); return View(); }改良ポイントまとめ
- 画像プレビュー:モーダル内で選択した画像を即表示。
- 重複チェック:同じ科目名が既に存在する場合は登録不可。
- GUID付きファイル名:ファイル名衝突を防止。
- リスト並び替え:再読み込み時にアルファベット順に整列。
この改良版なら、ユーザー体験が向上し、データの安全性
Powered by Froala Editor
-
添付画像
-
画像はありません
- Genreのカテゴリ-名
- Views