使用jQuery和部分视图在MVC中添加新的DropDownList项

我正在尝试创建一个调度MVC应用程序。 在ViewModel中,我组合了字段(来自CodeFirst EF字段)以包括会议主持人,访问者和时间等。我希望能够从这个表单中创建一个新的访问者(如果它们尚不存在)并通过Ajax回发到更新可用访问者列表。

视图模型:

public class AppointmentViewModel { public int HostID{ get; set; } public IEnumerable HostList{ get; set; } public int? VisitorID { get; set; } public IEnumerable VisitorList { get; set; } public string VisitorTitle { get; set; } public string VisitorFirstName{ get; set; } public string VisitorSurname { get; set; } public string VisitorCompany { get; set; } public DateTime VisitTime { get; set; } } 

控制器:

 public class AppointmentController : Controller { private VisitorManagerContext db = new VisitorManagerContext(); // GET: Appointment public ActionResult Create() { ViewBag.HostID = new SelectList(db.Hosts.OrderBy(x => x.Name), "id", "Name"); //ViewBag.VisitorID = new SelectList(db.Visitors.OrderBy(x => x.LastName).ThenBy(y => y.FirstName), "id", "VisitorName"); return View(new AppointmentViewModel() { HostList = db.Hosts.OrderBy(x => x.Name).Select(y => new SelectListItem() { Value = y.id.ToString(), Text = y.Name }), VisitorList = db.Visitors.OrderBy(x => x.LastName).ThenBy(y => y.FirstName).Select(z => new SelectListItem() { Value = z.id.ToString(), Text = z.Title + " " + z.FirstName + " " + z.LastName }) } ); } [HttpPost] public JsonResult CreateVisitor(AppointmentViewModel model) { var visitor = new Visitor() { Title = model.VisitorTitle, FirstName = model.VisitorFirstName, LastName = model.VisitorSurname }; db.Visitors.Add(visitor); db.SaveChanges(); return Json(visitor.id); } public PartialViewResult Add() { return PartialView(); } } 

视图:

 @model VisitorManager.Models.AppointmentViewModel @{ ViewBag.Title = "Create"; } 

Create

@using (Html.BeginForm()) { @Html.AntiForgeryToken()

AppointmentViewModel


@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.HostID, "HostID", htmlAttributes: new { @class = "control-label col-md-2" })
@Html.DropDownListFor(model => model.HostID, Model.HostList, "- Please select -", htmlAttributes: new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.HostID, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.VisitorID, "VisitorID", htmlAttributes: new { @class = "control-label col-md-2" })
@Html.DropDownListFor(model => model.VisitorID, Model.VisitorList, "- Please select -", htmlAttributes: new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.VisitorID, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.VisitTime, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.VisitTime, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.VisitTime, "", new { @class = "text-danger" })
}
@Html.ActionLink("Back to List", "Index")
@section Scripts { @Scripts.Render("~/bundles/jqueryval") $('#addVisitor').click( function () { $('#VisitorModal').load('@Url.Action("Add", "Appointment")'); } );

部分视图:

 @model VisitorManager.Models.AppointmentViewModel 
@Html.LabelFor(model => model.VisitorTitle, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.VisitorTitle, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.VisitorTitle, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.VisitorFirstName, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.VisitorFirstName, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.VisitorFirstName, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.VisitorSurname, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.VisitorSurname, new { htmlAttributes = new { @class = "form-control", @id="surname" } }) @Html.ValidationMessageFor(model => model.VisitorSurname, "", new { @class = "text-danger" })
@Html.LabelFor(model => model.VisitorCompany, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.VisitorCompany, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.VisitorCompany, "", new { @class = "text-danger" })
@section Scripts { $('#visitorform').submit(function () { var data = $(this).serialize(); var url = '@Url.Action("CreateVisitor", "Appointment")'; var text = $('#surname').val(); // a value from the form that you want as the option text $.post(url, data, function (response) { if (response) { $('#HostID').append($('').val(response).text(text)).val(response); } else { // Oops } }).fail(function () { // Oops }); // ... close the modal return false; // cancel the default submit }); }

我知道应该改进样式,并且应该以模态方式显示新的访问者表单,但是我希望在逻辑正常工作后修复。

单击“添加新访问者”将显示部分视图,包括将新访问者提交回控制器的按钮。 单击部分视图中的“创建”按钮将关闭视图,但表单数据不会提交回控制器。

有关为什么事件没有解雇的任何想法?

将新访问者添加到DropDownList后,我认为需要填写表单的其余部分并提交约会。

您没有id="visitorform"的第二个表单。 部分中的元素需要包含在

标记中

 @model VisitorManager.Models.AppointmentViewModel 
@Html.LabelFor(model => model.VisitorTitle, htmlAttributes: new { @class = "control-label col-md-2" })
@Html.EditorFor(model => model.VisitorTitle, new { htmlAttributes = new { @class = "form-control" } }) @Html.ValidationMessageFor(model => model.VisitorTitle, "", new { @class = "text-danger" })
.... // other elements for VisitorFirstName, VisitorSurname etc

请注意,您需要从partial中的按钮中删除id="visitorform"

您还需要从主视图的

标记移动部分并将其移动到结尾(嵌套表单是无效的html并且不受支持。

 @model VisitorManager.Models.AppointmentViewModel .... @using (Html.BeginForm()) { .... // elements associated with AppointmentViewModel only } // Move the partial/modal here 

你还应该将部分脚本移动到主视图中(脚本应该只在主视图或布局中)脚本还需要使用事件委托( .on() ),因为表单是动态添加的

 $('#VisitorModal').on('submit', '#visitorform', function () { var data = $(this).serialize(); .... 

旁注:你有一个多余的ViewBag.HostID = new SelectList(..)遗留在上一个问题中,应该从控制器方法中删除。