目前的情况: 对于这个问题的本质,我有两个数据库表/模型。在创建和添加新模型时,我使用AJAX表单从每个表中以列表形式更新显示的模型数据。实际上,页面永远不必重新加载以显示对列表的任何更改。
我为项目列表上方的每个模型静态显示创建表单。这适用于没有外键依赖关系的模型。但是,我的一个模型在创建表单中也有一个选择列表,该列表与页面上的其他模型列表相关联。
问题: 当我为更简单的模型添加记录时,具有外键依赖关系的模型的创建表单的选择列表不会更新以包括更改。我知道为什么它没有更新,我认为我需要使用AJAX完全就地重新创建创建表单或只更新选择列表。
有没有办法使用AJAX表单不仅可以更新我添加项目的模型列表,还可以同时更新包含创建表单的div?
我相信我已经包含了所有相关代码,希望能更清楚地了解我所要求的内容
示例创建更简单模型的表单:
@using (Ajax.BeginForm("_CreateCategory", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "list-categories"
}))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
<label class="control-label col-md-2">Name: </label>
<div class="col-md-5">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
<div class="col-md-5">
<input type="submit" value="Add" class="btn btn-success" />
</div>
</div>
</div>
}
具有外键依赖性的示例模型
@using (Ajax.BeginForm("_CreateType", new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "list-types"
}))
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
<label class="control-label col-md-2">Name: </label>
<div class="col-md-offset-1 col-md-6">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
<label class="control-label col-md-3">Category: </label>
<div class="col-md-6">
@Html.DropDownList("CategoryID", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.CategoryID, "", new { @class = "text-danger" })
</div>
<div class="col-md-3">
<input type="submit" value="Add" class="btn btn-success" />
</div>
</div>
</div>
}
具有外键的模型的示例列表部分视图
<div id="list-types">
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Category.Name)
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Category.Name)
</td>
<td>
@using (Ajax.BeginForm("DeleteType", new { id = item.ID }, new AjaxOptions()
{
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "list-types"
}))
{
@Html.AntiForgeryToken()
<button type="submit" class="no-default">
<span class="glyphicon glyphicon-remove"></span>
</button>
}
</td>
</tr>
}
</table>
</div>
用于添加更简单模型的控制器操作
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult _CreateCategory([Bind(Include = "ID, Name")] Category category)
{
if (ModelState.IsValid)
{
db.Categories.Add(category);
db.SaveChanges();
}
var categories = db.Categories;
return PartialView("_ListCategories", categories.ToList());
}
显示列表和创建表单的示例索引页面代码
<div class="col-lg-4 block">
<h3>Categories</h3>
@Html.Action("_CreateCategory")
@Html.Action("_ListCategories")
</div>
<div class="col-lg-4 block">
<h3>Types</h3>
@Html.Action("_CreateType")
@Html.Action("_ListTypes")
</div>
答案 0 :(得分:1)
您无法使用Ajax.BeginForm()
方法轻松完成此操作,并且无论如何,当您只向其添加一行时,再次返回整个表时会产生不必要的额外开销。
仅使用Ajax.BeginForm()
替换<form id="createcategory">
并使用$.ajax()
提交表单以创建新的Category
,并返回其ID。在成功回调中,您可以在表格中添加新行,并在第二种格式的<option>
中添加新的<select>
元素
var url = '@Url.Action("_CreateCategory")'
var categorySelect = $('#CategoryID');
$('#createcategory').submit(function() {
if (!$(this).valid()) {
return; // exit and display validation errors
}
var category = $(this).find('input[name="Name"]').val(); // see notes below
var formdata = $(this).serialize();
$.post(url, formdata, function(result) {
if (result.success) {
// Add option
categorySelect.append($('<option></option>').val(result.id).text(category));
// Add new table row
.... // You have not shown the view for _ListCategories but it might be somethng like
var cell = $('<td></td>').text(category);
var row = $('<tr></tr>').append(cell);
$('#yourTableID').append(row);
} else {
.... // check for errors, update the associated placeholder generated by ValidationMessageFor()
}
}).fail(function (result) {
// Oops something went wrong
});
}
$('#createtype').submit(function() {
// similar to above, but just add new table row based on the values of the form controls
});
并且控制器方法将是
[HttpPost]
[ValidateAntiForgeryToken]
public JsonResult _CreateCategory(Category category)
{
if (ModelState.IsValid)
{
db.Categories.Add(category);
db.SaveChanges();
// Get the new ID
int id = category.ID;
return Json(new { success = true, id = id });
}
// Get the validation errors
var errors = ModelState.Keys.Where(k => ModelState[k].Errors.Count > 0).Select(k => new { propertyName = k, errorMessage = ModelState[k].Errors[0].ErrorMessage });
return Json(new { success = false, errors = errors });
});
一些附注:
Name
的2个表单控件,以便您生成
重复的id
属性是无效的html。考虑删除
id
属性(使用new { id = "" }
或给其中一个属性
不同的id
属性。[Bind]
属性,在任何情况下都不需要
发送ID
的值,以便在保留的情况下排除
它。int
SelectedCategory
和IEnumerable<SelectListItem> CategoryList
和
在视图中使用DropDownListFor(m => m.SelectedCategory, Model.CategoryList,
"Please select", new { ... })
@Html.LabelFor(m => m.yourProperty)
正确生成您的
<label>
个元素(<label>
是一个辅助功能元素
单击它将焦点设置为关联的控件,而不是
与您当前的代码一起发生)