VB.Net MVC4在表单提交w / jQuery上创建高级实体

时间:2013-08-07 18:18:03

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

我有一个提交TimeItems集合(表对象)的表单,然后将其添加到数据库中。我遇到的问题是我希望允许用户在提交之前添加他们想要的尽可能多的或多个TimeItems。目前,TimeItem的输入字段包含外键的隐藏输入,用于选择员工的组合框,以及用于输入注释的基本输入框。我的视图,使用javascript:

<div>
    <img src="" alt="Add row" id="add-timesheet-row" />        
    @Using Html.BeginForm("AddToTimesheet", "Project")
        @<div>
            <input type="hidden" name="TimeItems[0].TaskID" value="@Model.TaskID"/>
            <select name="TimeItems[0].EmployeeID">
                @For Each emp As SelectListItem In ViewBag.EmployeeID
                    @<option value="@emp.Value">@emp.Text</option>
                Next
            </select>
            <input type="text" name="TimeItems[0].Notes" value="Test Notes" />

            <div id="add-row-target" style="display: none"></div>

            <div class="button-submit">
                <input type="submit" value="Create" /> |
                @Html.ActionLink("Back", "Index")
            </div>
        </div>
    End Using
</div>

<script type="text/javascript">
    $(document).ready(function () {
        $("#add-timesheet-row").click(function () {
            $.get('@Url.Action("RenderTimeItems", New With {.id = Model.TaskID})', function(data) {
                $('#add-row-target').before(data);
            });
        });
    });
</script>

这里发生的是当点击“添加行”img时,javascript返回RenderTimeItems动作,该动作又返回局部视图。该局部视图再次包含输入html(隐藏,组合和文本框):

<input type="hidden" name="TimeItems[#].TaskID" value="@Model.TaskID"/>
<select name="TimeItems[#].EmployeeID">
    @For Each emp As SelectListItem In ViewBag.EmployeeID
        @<option value="@emp.Value">@emp.Text</option>
    Next
</select>
<input type="text" name="TimeItems[#].Notes" value="Test Notes" />

然后将此html添加到原始表单中。我的部分视图的问题是TimeItems[#]中的“#”需要是一个实际数字,并且每次用户单击“添加行”以使我的控制器能够正确解释TimeItems的集合时需要递增。请注意,在我的原始视图中,TimeItems[0]用于初始TimeItem,因此我的局部视图中的下一个应该是TimeItems[1]。如何跟踪数字,在主视图中单击“添加行”时增加它,但在调用RenderTimeItems后仍然可以在局部视图中访问它?

当用户提交表单时,它将转到AddToTimesheet操作,该操作使用该集合并将每个单独的TimeItem添加到数据库中,如同this example中所示:

<HttpPost()>
Function AddToTimesheet(ByVal TimeItems() As ppTimeItem) As ActionResult
    If TimeItems IsNot Nothing Then
        For Each time In TimeItems
            db.ppTimeItems.Add(time)
            db.SaveChanges()
        Next
    End If
    Return RedirectToAction("Index")
End Function

此外,如果我想在提交表单之前允许用户删除TimeItem(他们之前添加的),这将从集合中删除索引,该索引必须包含并发索引才能正常工作。即如果添加了TimeItems[0]TimeItems[1]TimeItems[2],然后用户删除了TimeItems[1],则无法再正确添加TimeItems[2],因为其余的指数是0和2.任何想法?

1 个答案:

答案 0 :(得分:1)

您首先需要跟踪页面上有多少个TimeItem行,因此您需要在每一行上都有一些东西。 add-row-target会有效,但我建议您为<div>提供类似“timeItem”的课程:

var numItems = $("#add-row-target").length;

您可以继续返回部分视图,在$.get回调中只需将data中的“#”替换为numItems

$.get('@Url.Action("RenderTimeItems", New With {.id = Model.TaskID})', function(data) {
                var dataWithNumber = data.replace(/#/g , numItems);
                $('#add-row-target').before(dataWithNumber);
            });

或者,您可以将数字传递给返回部分

的操作方法
$.get('@Url.Action("RenderTimeItems", New With {.id = Model.TaskID})?number=' + numItems 


<input type="hidden" name="TimeItems[@Model.Number].TaskID" value="@Model.TaskID"/>
<select name="TimeItems[@Model.Number].EmployeeID">
    @For Each emp As SelectListItem In ViewBag.EmployeeID
        @<option value="@emp.Value">@emp.Text</option>
    Next
</select>
<input type="text" name="TimeItems[@Model.Number].Notes" value="Test Notes" />