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

时间:2016-07-17 05:22:24

标签: jquery asp.net asp.net-mvc entity-framework razor

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

视图模型:

public class AppointmentViewModel
{
    public int HostID{ get; set; }
    public IEnumerable<SelectListItem> HostList{ get; set; }
    public int? VisitorID { get; set; }
    public IEnumerable<SelectListItem> 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";
}

<h2>Create</h2>

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

    <div class="form-horizontal">
        <h4>AppointmentViewModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.HostID, "HostID", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.HostID, Model.HostList, "- Please select -", htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.HostID, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.VisitorID, "VisitorID", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.VisitorID, Model.VisitorList, "- Please select -", htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.VisitorID, "", new { @class = "text-danger" })
            </div>
            <button type="button" id="addVisitor">Add new Visitor</button>
        </div>

        <div id="VisitorModal"></div>

        <div class="form-group">
            @Html.LabelFor(model => model.VisitTime, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.VisitTime, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.VisitTime, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Save" class="btn btn-default" />
            </div>
        </div>

    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>


@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")

    <script type="text/javascript">
        $('#addVisitor').click(
            function () {
                $('#VisitorModal').load('@Url.Action("Add", "Appointment")');
            }
        );


    </script>

部分视图:

@model VisitorManager.Models.AppointmentViewModel


    <div class="form-group">
        @Html.LabelFor(model => model.VisitorTitle, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.VisitorTitle, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.VisitorTitle, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.VisitorFirstName, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.VisitorFirstName, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.VisitorFirstName, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.VisitorSurname, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.VisitorSurname, new { htmlAttributes = new { @class = "form-control", @id="surname" } })
            @Html.ValidationMessageFor(model => model.VisitorSurname, "", new { @class = "text-danger" })
        </div>
    </div>

    <div class="form-group">
        @Html.LabelFor(model => model.VisitorCompany, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.VisitorCompany, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.VisitorCompany, "", new { @class = "text-danger" })
        </div>
    </div>

<div class="form-group">
    <div class="col-md-offset-2 col-md-10">
        <input type="submit" value="Create" class="btn btn-default" id="visitorform" />
    </div>
</div>

@section Scripts {
    <script type="text/javascript">
        $('#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($('<option></option>').val(response).text(text)).val(response);
                } else {
                    // Oops
                }
            }).fail(function () {
                // Oops
            });
            // ... close the modal
            return false; // cancel the default submit
        });
</script>}

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

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

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

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

1 个答案:

答案 0 :(得分:1)

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

@model VisitorManager.Models.AppointmentViewModel
<form id="visitorform">
    <div class="form-group">
        @Html.LabelFor(model => model.VisitorTitle, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.EditorFor(model => model.VisitorTitle, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.VisitorTitle, "", new { @class = "text-danger" })
        </div>
    </div>
    .... // other elements for VisitorFirstName, VisitorSurname etc
    <div class="form-group">
        <div class="col-md-offset-2 col-md-10">
            <input type="submit" value="Create" class="btn btn-default" />
        </div>
    </div>
</form>

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

您还需要从主视图的<form>标记中移动部分并将其移动到结尾(嵌套表单是无效的html,不受支持。

@model VisitorManager.Models.AppointmentViewModel
....
@using (Html.BeginForm())
{
.... // elements associated with AppointmentViewModel only
}
// Move the partial/modal here
<div id="VisitorModal"></div>

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

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

旁注:您之前的问题遗留了多余的ViewBag.HostID = new SelectList(..),应该从控制器方法中删除。