ASP.NET Core MVC:JQuery模态框增改后刷新局部视图求助
问题:模态框添加数据后局部视图无法正确更新
我已经折腾好几天了,需求是通过jQuery弹出模态框向数据库添加新值后,只更新页面中的局部视图,不刷新包含下拉列表和按钮的主视图。目前代码能成功创建新条目,但会把列表局部视图当成独立页面打开,而不是更新原页面里的局部视图。以下是相关代码:
主视图
@{ ViewData["Title"] = "Manage DropDown Lists"; //Layout = "~/Views/Shared/_Layout.cshtml"; } <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous"> <h1>Manage Lists</h1> <p> Select List: @Html.DropDownList("ddl", ViewData["selected"] as List<SelectListItem>) <button id="btn-ddl" data-url='@Url.Action("Index", "param")' class="js-load-partial; btn btn-primary btn-sm">Get List</button> </p> <hr /> <br /> <div id="detailsDiv"> </div> @section Scripts { <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.1/jquery.min.js" integrity="sha512-aVKKRRi/Q/YV+4mjoKBsE4x3H+BkegoM/em46NNlCqNTmUYADjBbeNefNxYV7giUp0VxICtqdrbqU7iVaeZNXA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="~/js/site.js"></script> }
按钮点击的JQuery代码(btn-ddl)
//Render PartialView from Button click - input Id from DropDownList - Manage Lists $(document).ready(function () { $("body").on("click", '#btn-ddl', function (evt) { var $detailDiv = $('#detailsDiv'), url = $(this).data('url'); url = url.replace("param", $("#ddl").val()); $.get(url, function (data) { $detailDiv.html(data); }); }); });
渲染的局部视图之一
@model IEnumerable<PoCStaffDatabase.Models.AccessLevel> <div> <h1>Access Levels</h1> <br /> <hr /> </div> <div id="PlaceHolderHere"> <!-- Modal Popup Placeholder --> </div> <button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#addAccessLevel" data-url="@Url.Action("Create")" id="showModalPopup"> Create </button> <br /><br /> <table class="table"> <thead> <tr> <th> @Html.DisplayNameFor(model => model.AccessLevelName) </th> <th> @Html.DisplayNameFor(model => model.Live) </th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model) { <tr> <td> @Html.DisplayFor(modelItem => item.AccessLevelName) </td> <td> @Html.DisplayFor(modelItem => item.Live) </td> <td> <a asp-action="Edit" asp-route-id="@item.AccessLevelId">Edit</a> </td> </tr> } </tbody> </table>
作为模态框弹出的创建局部视图
@model PoCStaffDatabase.Models.AccessLevel <div class="modal fade" id="addAccessLevel" tabindex="-1" role="dialog" aria-labelledby="addAccessLevelLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="addAccessLevelLabel">Add Access Level</h5> <button type="button" class="close" data-dismiss="modal" id="btnClose" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form asp-action="Create"> <div class="form-group"> <label asp-for="AccessLevelName" class="control-label"></label> <input asp-for="AccessLevelName" class="form-control" /> <span asp-validation-for="AccessLevelName" class="text-danger"></span> </div> <div class="form-group form-check"> <label class="form-check-label"> <input class="form-check-input" asp-for="Live" /> @Html.DisplayNameFor(model => model.Live) </label> </div> <div class="modal-footer"> <button type="button" class="btn btn-danger" data-dismiss="modal" id="btnClose" >Cancel</button> <button type="submit" class="btn btn-primary" data-save="modal" data-url='@Url.Action("Index", "AccessLevels")'id="btnSave">Create New</button> </div> </form> </div> </div> </div> </div>
"Create New"按钮的JQuery代码(btnSave)
$(document).ready(function () { $('body').on("click", '#showModalPopup', function (event) { var PlaceHolderElement = $('#PlaceHolderHere'), url = $(this).data('url'); PlaceHolderElement.empty(); $.get(url, function (data) { PlaceHolderElement.html(data); PlaceHolderElement.find('.modal').modal('show'); }); }); PlaceHolderElement.on("click", '#btnSave', function (event) { form = $(this).parents('.modal').find('form'), actionUrl = form.attr('action'), sendData = form.serialize(); $.post(actionUrl, sendData).done(function (data) { PlaceHolderElement.find('.modal').modal('hide'); }); // var $detailDiv = ('#detailsDiv'), // url = $(this).data('url'); // // $.get(url, function (data) { // $detailDiv.html(data); // }); }); });
Create和Index操作的控制器代码
namespace PoCStaffDatabase.Controllers { public class AccessLevelsController : Controller { private readonly AppDbContext _context; public AccessLevelsController(AppDbContext context) { _context = context; } // GET: AccessLevels public async Task<IActionResult> Index() { var accesslevel = await _context.AccessLevel.ToListAsync(); return PartialView("_partialIndex", accesslevel); //return View(await _context.AccessLevel.ToListAsync()); } // GET: AccessLevels/Details/5 public async Task<IActionResult> Details(int? id) { if (id == null) { return NotFound(); } var accessLevel = await _context.AccessLevel .FirstOrDefaultAsync(m => m.AccessLevelId == id); if (accessLevel == null) { return NotFound(); } return View(accessLevel); } // GET: AccessLevels/Create public IActionResult Create() { AccessLevel accesslevel = new AccessLevel(); return PartialView("_partialCreate", accesslevel); } // POST: AccessLevels/Create // To protect from overposting attacks, enable the specific properties you want to bind to, for // more details, see http://go.microsoft.com/fwlink/?LinkId=317598. [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("AccessLevelId,AccessLevelName,Live")] AccessLevel accessLevel) { if (ModelState.IsValid) { _context.Add(accessLevel); await _context.SaveChangesAsync(); //return NoContent(); return RedirectToAction("Index"); //return PartialView("_partialIndex", await _context.AccessLevel.ToListAsync() ); } return View(accessLevel); } } }
解决方案
问题出在两个核心点,修改后即可实现局部更新:
1. 修改控制器POST Create方法的返回值
当前代码用return RedirectToAction("Index");会触发浏览器跳转,把局部视图当成独立页面打开。需要改成直接返回更新后的局部视图:
[HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Create([Bind("AccessLevelId,AccessLevelName,Live")] AccessLevel accessLevel) { if (ModelState.IsValid) { _context.Add(accessLevel); await _context.SaveChangesAsync(); // 返回更新后的局部视图,而非跳转 var accessLevels = await _context.AccessLevel.ToListAsync(); return PartialView("_partialIndex", accessLevels); } // 验证失败时返回模态框局部视图,保留用户输入 return PartialView("_partialCreate", accessLevel); }
2. 完善前端btnSave的AJAX回调逻辑
目前仅隐藏模态框,未更新页面中的局部视图。需要在POST成功后,将返回的局部视图内容替换到主页面的容器中:
$(document).ready(function () { $('body').on("click", '#showModalPopup', function (event) { var PlaceHolderElement = $('#PlaceHolderHere'), url = $(this).data('url'); PlaceHolderElement.empty(); $.get(url, function (data) { PlaceHolderElement.html(data); PlaceHolderElement.find('.modal').modal('show'); }); }); // 绑定到body确保动态加载的模态框能触发事件 $('body').on("click", '#btnSave', function (event) { // 阻止表单默认提交行为 event.preventDefault(); var form = $(this).parents('.modal').find('form'), actionUrl = form.attr('action'), sendData = form.serialize(); $.post(actionUrl, sendData).done(function (data) { var PlaceHolderElement = $('#PlaceHolderHere'); PlaceHolderElement.find('.modal').modal('hide'); // 更新主页面的局部视图容器 $('#detailsDiv').html(data); }).fail(function() { alert('添加失败,请重试'); }); }); });
内容的提问来源于stack exchange,提问作者SND69
相关产品推荐
相关产品推荐

