我有一个表单,它正在提交一个TimeItems集合(一个表对象),然后将这些集合添加到数据库中。我遇到的问题是,我希望允许用户在提交之前向集合中添加任意数量的TimeItems。目前,TimeItem的输入字段包括一个外键的隐藏输入、一个选择员工的组合框和一个输入注释的基本输入框
<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的集合。请注意,在我的原始视图中,初始TimeItem使用了TimeItems[0]
,因此我的局部视图中的下一个应该是TimeItems[1]
。如何跟踪一个数字,在主视图中单击"添加行"时递增,但在调用RenderTimeItems后仍在部分视图中访问它?
当用户提交表单时,它进入AddToTimesheet操作,该操作消耗集合并将每个单独的TimeItem添加到数据库中,如本例所示:
<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。有什么想法吗?
您首先需要跟踪页面上有多少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" />