- 首页
- 前端开发
- 使用 Html.BeginCollectionItem 帮助程序传递集合的局部视图
使用 Html.BeginCollectionItem 帮助程序传递集合的局部视图
[英] A Partial View passing a collection using the Html.BeginCollectionItem helper
本文介绍了使用 Html.BeginCollectionItem 帮助程序传递集合的局部视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我做了一个小项目来理解 Stephen Muecke 的答案:向控制器提交多次调用数据的同一个局部视图?
几乎一切正常.javascript 从局部视图中添加了新字段,我可以通过控制器方法为局部视图插入的临时"值判断它们已绑定到模型.
但是,当我提交新字段时,AddRecord() 方法抛出一个异常,表明模型没有被传入(对象引用未设置到对象的实例").
此外,当我查看页面源代码时,BeginCollectionItem 助手会在主视图中的表格周围插入一个隐藏标记,因为它应该显示预先存在的记录,但不在 javascript 添加的新字段周围.>
我做错了什么?我是新手,感谢您的耐心等待!
我的主要观点:
@model IEnumerable@using (Html.BeginForm("AddDetail", "CashRecipients", FormMethod.Post)){@Html.AntiForgeryToken()<div id="CSQGroup">
}<div><input type="button" value="添加字段" id="addField" onclick="addFieldss()"/>
<脚本>函数 addFieldss(){//警报(ajax调用");$.ajax({url: '@Url.Content("~/CashRecipients/RecipientForm")',类型:'获取',成功:功能(结果){//警报(成功");var newDiv = document.createElement("div");var newContent = document.createTextNode("你好,问候!");newDiv.appendChild(newContent);newDiv.innerHTML = 结果;var currentDiv = document.getElementById("div1");document.getElementById("CSQGroup").appendChild(newDiv);},错误:函数(结果){警报(失败");}});}
我的部分视图:
@model DynamicForm.Models.CashRecipient@using HtmlHelpers.BeginCollectionItem@using (Html.BeginCollectionItem("recipients")){<div class="editor-field">@Html.LabelFor(model => model.Id)@Html.LabelFor(model => model.cashAmount)@Html.TextBoxFor(model =>model.cashAmount)@Html.LabelFor(model => model.recipientName)@Html.TextBoxFor(model => model.recipientName)
<div class="form-group"><div class="col-md-offset-2 col-md-10"><input type="submit" value="Save" class="btn btn-default"/>
}
我的模型:
公共类 CashRecipient{公共 int Id { 获取;放;}公共字符串 cashAmount { 获取;放;}公共字符串收件人姓名 { 获取;放;}}
在我的控制器中:
[HttpPost][验证AntiForgeryToken]public ActionResult AddDetail([Bind(Include = "Id,cashAmount,recpientName")] IEnumerable cashRecipient){如果(模型状态.IsValid){foreach (CashRecipient p in cashRecipient) {db.CashRecipients.Add(p);}db.SaveChanges();return RedirectToAction("索引");}返回视图(cashRecipient);}公共 ActionResult RecipientForm(){var data = new CashRecipient();data.cashAmount = "临时";data.recipientName = "temp";返回部分视图(数据);}
解决方案
首先创建一个视图模型来表示您要编辑的内容.我假设 cashAmount
是一个货币值,因此应该是一个小数(根据需要添加其他验证和显示属性)
公共类 CashRecipientVM{公众号?身份证{得到;放;}公共十进制金额{得到;放;}[必填(ErrorMessage = "请输入收件人姓名")]公共字符串收件人{ 获取;放;}}
然后创建一个局部视图(比如说)_Recipient.cshtml
@model CashRecipientVM<div class="收件人">@using (Html.BeginCollectionItem("recipients")){@Html.HiddenFor(m => m.ID, new { @class="id" })@Html.LabelFor(m => m.Recipient)@Html.TextBoxFor(m => m.Recipient)@Html.ValidationMesssageFor(m => m.Recipient)@Html.LabelFor(m => m.Amount)@Html.TextBoxFor(m => m.Amount)@Html.ValidationMesssageFor(m => m.Amount)<button type="button" class="delete">Delete</button>}
以及返回该部分的方法
public PartialViewResult Recipient(){return PartialView("_Recipient", new CashRecipientVM());}
那么你的主要 GET 方法将是
public ActionResult Create(){List模型 = 新列表();....//添加您编辑的任何现有对象返回视图(模型);}
它的视图将是
@model IEnumerable@using (Html.BeginForm()){<div id="收件人">foreach(模型中的var接收者){@Html.Partial("_Recipient", 收件人)}<button id="add" type="button">添加</button><input type="submit" value="保存"/>}
并将包含一个脚本来为新的 CashRecipientVM
添加 htmlvar url = '@Url.Action("Recipient")';var form = $('form');var 收件人 = $('#recipients');$('#add').click(function() {$.get(url, function(response) {收件人.追加(响应);//重新解析验证器以进行客户端验证form.data('验证器', null);$.validator.unobtrusive.parse(form);});});
和删除项目的脚本
$('.delete').click(function() {var container = $(this).closest('.recipient');var id = container.find('.id').val();如果(身份证){//使ajax post删除项目$.post(yourDeleteUrl, { id: id }, function(result) {容器.remove();}.fail(函数(结果){//糟糕,出了点问题(显示错误信息?)}} 别的 {//它从未存在过,所以只需移除容器容器.remove();}});
并且表单将回发到
public ActionResult Create(IEnumerable收件人)
I made a small project to understand the answer from Stephen Muecke here: Submit same Partial View called multiple times data to controller?
Almost everything works. The javascript adds new fields from the Partial View, and I can tell they're bound to the model by the "temp" values inserted by the controller method for the partial view.
However, when I submit the new fields the AddRecord() method throws an exception showing that the model isn't getting passed in ("Object reference not set to an instance of an object").
Also, when I view the page source, the BeginCollectionItem helper is inserting a hidden tag as it should around the table in the main view that displays pre-existing records, but not around the new fields that the javascript adds.
What am I doing wrong? I'm pretty new at this so thanks for your patience!
My main view:
@model IEnumerable<DynamicForm.Models.CashRecipient>
@using (Html.BeginForm("AddDetail", "CashRecipients", FormMethod.Post))
{
@Html.AntiForgeryToken()
<div id="CSQGroup">
</div>
}
<div>
<input type="button" value="Add Field" id="addField" onclick="addFieldss()" />
</div>
<script>
function addFieldss()
{
//alert("ajax call");
$.ajax({
url: '@Url.Content("~/CashRecipients/RecipientForm")',
type: 'GET',
success:function(result) {
//alert("Success");
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hi there and greetings!");
newDiv.appendChild(newContent);
newDiv.innerHTML = result;
var currentDiv = document.getElementById("div1");
document.getElementById("CSQGroup").appendChild(newDiv);
},
error: function(result) {
alert("Failure");
}
});
}
</script>
My Partial View:
@model DynamicForm.Models.CashRecipient
@using HtmlHelpers.BeginCollectionItem
@using (Html.BeginCollectionItem("recipients"))
{
<div class="editor-field">
@Html.LabelFor(model => model.Id)
@Html.LabelFor(model => model.cashAmount)
@Html.TextBoxFor(model => model.cashAmount)
@Html.LabelFor(model => model.recipientName)
@Html.TextBoxFor(model => model.recipientName)
</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>
}
My model:
public class CashRecipient
{
public int Id { get; set; }
public string cashAmount { get; set; }
public string recipientName { get; set; }
}
In my controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddDetail([Bind(Include = "Id,cashAmount,recpientName")] IEnumerable<CashRecipient> cashRecipient)
{
if (ModelState.IsValid)
{
foreach (CashRecipient p in cashRecipient) {
db.CashRecipients.Add(p);
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(cashRecipient);
}
public ActionResult RecipientForm()
{
var data = new CashRecipient();
data.cashAmount = "temp";
data.recipientName = "temp";
return PartialView(data);
}
解决方案
First start by creating a view model to represent what you want to edit. I'm assuming cashAmount
is a monetary value, so therefore should be a decimal (add other validation and display attributes as required)
public class CashRecipientVM
{
public int? ID { get; set; }
public decimal Amount { get; set; }
[Required(ErrorMessage = "Please enter the name of the recipient")]
public string Recipient { get; set; }
}
Then create a partial view (say) _Recipient.cshtml
@model CashRecipientVM
<div class="recipient">
@using (Html.BeginCollectionItem("recipients"))
{
@Html.HiddenFor(m => m.ID, new { @class="id" })
@Html.LabelFor(m => m.Recipient)
@Html.TextBoxFor(m => m.Recipient)
@Html.ValidationMesssageFor(m => m.Recipient)
@Html.LabelFor(m => m.Amount)
@Html.TextBoxFor(m => m.Amount)
@Html.ValidationMesssageFor(m => m.Amount)
<button type="button" class="delete">Delete</button>
}
</div>
and a method to return that partial
public PartialViewResult Recipient()
{
return PartialView("_Recipient", new CashRecipientVM());
}
Then your main GET method will be
public ActionResult Create()
{
List<CashRecipientVM> model = new List<CashRecipientVM>();
.... // add any existing objects that your editing
return View(model);
}
and its view will be
@model IEnumerable<CashRecipientVM>
@using (Html.BeginForm())
{
<div id="recipients">
foreach(var recipient in Model)
{
@Html.Partial("_Recipient", recipient)
}
</div>
<button id="add" type="button">Add</button>
<input type="submit" value="Save" />
}
and will include a script to add the html for a new CashRecipientVM
var url = '@Url.Action("Recipient")';
var form = $('form');
var recipients = $('#recipients');
$('#add').click(function() {
$.get(url, function(response) {
recipients.append(response);
// Reparse the validator for client side validation
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
});
and the script to delete an item
$('.delete').click(function() {
var container = $(this).closest('.recipient');
var id = container.find('.id').val();
if (id) {
// make ajax post to delete item
$.post(yourDeleteUrl, { id: id }, function(result) {
container.remove();
}.fail(function (result) {
// Oops, something went wrong (display error message?)
}
} else {
// It never existed, so just remove the container
container.remove();
}
});
And the form will post back to
public ActionResult Create(IEnumerable<CashRecipientVM> recipients)
这篇关于使用 Html.BeginCollectionItem 帮助程序传递集合的局部视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文