使用 jQuery dialog/partial 视图创建 child object
Create child object using jQuery dialog/partial view
我正在使用 MVC 5/jquery 1.10.2 和 jquery ui 1.11.3
对于这个例子,我有一个 Parent object 和一个 child object。在 parent object 的创建视图上,我有一个 auto-complete 文本框,用户可以从中选择 children 之一。如果 child 尚不存在,则有一个 link 供用户单击以打开包含部分视图的 jQuery 对话框。
我用来执行此操作的代码如下:
$(function () {
var dialog = $("#dialog-form").dialog({
autoOpen: false,
width: 500,
height: 450,
dialogClass: "dialogStyle",
draggable: true,
resizable: false,
modal: true,
hide: { effect: "fade", duration: 1000 },
title: "New Donor",
open: function () {
$(this).closest(".ui-dialog")
.find(".ui-dialog-titlebar-close")
//.removeclass("ui-dialog-titlebar-close")
.html("<span class='ui-button-icon-primary ui-icon ui-icon-closethick'></span><span class='ui-button-text'>close</span>");
}
});
$("#new-donor").click(function () {
$("#dialog-form").load("@Url.Action("MinCreate", "Donors")", function () {
dialog.dialog("open")
});
});
});
现在,我有两个问题:
- 当我成功提交部分视图表单后,我想关闭对话框并将新创建的 child 详细信息 return 放入现有的 parent 表单中。我不知道该怎么做。
- 如果在服务器端的局部视图上验证失败,我想显然 return 现有对话框的失败。目前它将重定向到局部视图。
我的局部视图代码在这里:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label dia-col-md-2" })
<div class="dia-col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
// other data entry fields here...
<div class="form-group">
<div class="dia-col-md-offset-2 dia-col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
我的控制器代码在这里:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> MinCreate([Bind(Include = "Id,Name,Email,AddressLine1,City,State,PostalCode,PrimaryPhone")] Donor donor)
{
try
{
if (ModelState.IsValid)
{
db.Donors.Add(donor);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
}
catch (Exception ex)
{
return PartialView("_Create");
}
return PartialView("_Create", donor);
}
jQuery 似乎是最好的方法; Razor ajax 助手对我来说总是有点笨拙。
在进入那个部分之前,先看看你的部分;虽然您有一个 div 元素,其 class 设置为水平形式,但在局部视图中您实际上没有 form。使用 Razor 助手 @using (Html.BeginForm(....))
或使用 <form name="this_form" id="this_form" method="post">
添加表单
正确设置表单后,您可以将一些 Javascript 添加到您的 partialView 并使用 jQuery 提交表单,然后在成功 posting 表单后,您可以执行 $.get() 更新父表单的内容,或者如果 post 失败,则执行其他操作:
var stuff = $('#this_form').serialize();
$.post(url_to_your_controller_action, stuff, function (data) {
// do a $.get() to retrieve updated data then use jQuery to update your parent form
}).fail(function () {
// do other stuff...
})
好的,所以我花了几天时间思考这个问题,我 认为 scurrie 可能一直在试图指出我这个方向。以下是我提出的解决方案:
- 我必须从 parent 视图启动所有 JavaScript 代码。
- 我在局部使用了 Ajax 表单并使用了对话框 "Submit" 按钮
调用 $.ajax 并发送我的表单数据并定义一个 "success" 事件。
- 成功事件检查来自控制器的 return 值,如果
我设置 retObject.success == true 然后它在
parent 表单并设置捐助者姓名和 ID,然后我关闭 jQuery
对话。
- 如果 retObject.success 为 null 那么我知道我已经 returned
无效的 ModelState 所以我将 return 值设置为对话框
使用 jQuery 选择器形成 .html 属性。
我大概理解下面 95% 的内容,所以可能有一些不必要的代码。如果您看到可以做得更好的东西,请告诉我!
我的部分视图(Donors/_Create.cshtml - 注意没有 html 提交按钮,因为我使用的是 jQuery 对话框命令中的提交按钮:
@using (Ajax.BeginForm("MinCreate", "Donors", new AjaxOptions() { HttpMethod = "Post", InsertionMode = InsertionMode.Replace}, new { id = "DonorForm" })){
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label dia-col-md-2" })
<div class="dia-col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @id = "DonorFormName", @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<More Form Fields... />
</div>
}
我的 Parent 表单 (Items/Create.cshtml):
<script>
$(function () {
$("#DonorName").autocomplete({
source: '@Url.Action("Autocomplete")',
select: function (event, ui) {
$("#DonorId").val(ui.item.value);
$("#DonorName").val(ui.item.label);
return false;
},
focus: function (event, ui)
{
$("#DonorName").val(ui.item.label);
return false;
},
change: function (e, ui) {
if (!ui.item)
{
$("#dialog-form").load("@Url.Action("MinCreate", "Donors")", function () {
$("#DonorFormName").val(e.target.value);
dialog.dialog("open");
$("#DonorFormEmail").focus();
e.target.value = "";
});
}
}
});
var dialog = $("#dialog-form").dialog({
autoOpen: false,
width: 500,
height: 475,
dialogClass: "dialogStyle",
draggable: true,
resizable: false,
modal: true,
hide: { effect: "fade", duration: 1000 },
title: "New Donor",
open: function () {
$(this).closest(".ui-dialog")
.find(".ui-dialog-titlebar-close")
.html("<span class='ui-button-icon-primary ui-icon ui-icon-closethick'></span><span class='ui-button-text'>close</span>");
},
buttons: {
Submit: function () {
$.ajax({
url: "@Url.Action("MinCreate", "Donors")",
type: "POST",
data: $("#DonorForm").serialize(),
success: function (data) {
if (data.success) {
$("#dialog-form").dialog("close");
$("#DonorId").val(data.retObject.Id);
$("#DonorName").val(data.retObject.Name);
}
else {
$("#dialog-form").html(data);
}
}
});
return false;
},
}
});
$("#new-donor").click(function () {
$("#dialog-form").load("@Url.Action("MinCreate", "Donors")", function () {
dialog.dialog("open")
});
});
});
@using (Html.BeginForm()) {
<div class="form-horizontal" id="CreateItem">
<h4>Item</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Donor.Name, "Donor", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Donor.Name, new { htmlAttributes = new { @class = "form-control", @id = "DonorName" } })<a href="#" id="new-donor">New Donor</a>
@*<input name="donor" class="control-label col-md-2" data-trf-autocomplete="@Url.Action("Autocomplete")" />*@
@Html.HiddenFor(model => model.DonorId, new { htmlAttributes = new { @id = "DonorId" } })
@Html.ValidationMessageFor(model => model.DonorId, "", new { @class = "text-danger" })
</div>
</div>
<More unimportant form fields... />
</div>
<div id="dialog-form"></div>
}
最后来自控制器的代码 Donors/MinCreate 动作:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MinCreate([Bind(Include = "Id,Name,Email,AddressLine1,City,State,PostalCode,PrimaryPhone")] Donor donor)
{
try
{
if (ModelState.IsValid)
{
db.Donors.Add(donor);
db.SaveChanges();
var result = new { success = true, retObject = donor };
return Json(result, JsonRequestBehavior.DenyGet);
}
}
catch (Exception ex)
{
return Json(new { success = false, retObject = donor });
}
return PartialView("_Create", donor);
}
我知道这里可能有很多无用的废话,但我是 MVC 的新手,一个确切的例子正是我所需要的。所以,我希望有人觉得这很有用。
我正在使用 MVC 5/jquery 1.10.2 和 jquery ui 1.11.3
对于这个例子,我有一个 Parent object 和一个 child object。在 parent object 的创建视图上,我有一个 auto-complete 文本框,用户可以从中选择 children 之一。如果 child 尚不存在,则有一个 link 供用户单击以打开包含部分视图的 jQuery 对话框。
我用来执行此操作的代码如下:
$(function () {
var dialog = $("#dialog-form").dialog({
autoOpen: false,
width: 500,
height: 450,
dialogClass: "dialogStyle",
draggable: true,
resizable: false,
modal: true,
hide: { effect: "fade", duration: 1000 },
title: "New Donor",
open: function () {
$(this).closest(".ui-dialog")
.find(".ui-dialog-titlebar-close")
//.removeclass("ui-dialog-titlebar-close")
.html("<span class='ui-button-icon-primary ui-icon ui-icon-closethick'></span><span class='ui-button-text'>close</span>");
}
});
$("#new-donor").click(function () {
$("#dialog-form").load("@Url.Action("MinCreate", "Donors")", function () {
dialog.dialog("open")
});
});
});
现在,我有两个问题:
- 当我成功提交部分视图表单后,我想关闭对话框并将新创建的 child 详细信息 return 放入现有的 parent 表单中。我不知道该怎么做。
- 如果在服务器端的局部视图上验证失败,我想显然 return 现有对话框的失败。目前它将重定向到局部视图。
我的局部视图代码在这里:
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label dia-col-md-2" })
<div class="dia-col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
// other data entry fields here...
<div class="form-group">
<div class="dia-col-md-offset-2 dia-col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
我的控制器代码在这里:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> MinCreate([Bind(Include = "Id,Name,Email,AddressLine1,City,State,PostalCode,PrimaryPhone")] Donor donor)
{
try
{
if (ModelState.IsValid)
{
db.Donors.Add(donor);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
}
catch (Exception ex)
{
return PartialView("_Create");
}
return PartialView("_Create", donor);
}
jQuery 似乎是最好的方法; Razor ajax 助手对我来说总是有点笨拙。
在进入那个部分之前,先看看你的部分;虽然您有一个 div 元素,其 class 设置为水平形式,但在局部视图中您实际上没有 form。使用 Razor 助手 @using (Html.BeginForm(....))
或使用 <form name="this_form" id="this_form" method="post">
正确设置表单后,您可以将一些 Javascript 添加到您的 partialView 并使用 jQuery 提交表单,然后在成功 posting 表单后,您可以执行 $.get() 更新父表单的内容,或者如果 post 失败,则执行其他操作:
var stuff = $('#this_form').serialize();
$.post(url_to_your_controller_action, stuff, function (data) {
// do a $.get() to retrieve updated data then use jQuery to update your parent form
}).fail(function () {
// do other stuff...
})
好的,所以我花了几天时间思考这个问题,我 认为 scurrie 可能一直在试图指出我这个方向。以下是我提出的解决方案:
- 我必须从 parent 视图启动所有 JavaScript 代码。
- 我在局部使用了 Ajax 表单并使用了对话框 "Submit" 按钮 调用 $.ajax 并发送我的表单数据并定义一个 "success" 事件。
- 成功事件检查来自控制器的 return 值,如果 我设置 retObject.success == true 然后它在 parent 表单并设置捐助者姓名和 ID,然后我关闭 jQuery 对话。
- 如果 retObject.success 为 null 那么我知道我已经 returned 无效的 ModelState 所以我将 return 值设置为对话框 使用 jQuery 选择器形成 .html 属性。
我大概理解下面 95% 的内容,所以可能有一些不必要的代码。如果您看到可以做得更好的东西,请告诉我!
我的部分视图(Donors/_Create.cshtml - 注意没有 html 提交按钮,因为我使用的是 jQuery 对话框命令中的提交按钮:
@using (Ajax.BeginForm("MinCreate", "Donors", new AjaxOptions() { HttpMethod = "Post", InsertionMode = InsertionMode.Replace}, new { id = "DonorForm" })){
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Name, htmlAttributes: new { @class = "control-label dia-col-md-2" })
<div class="dia-col-md-10">
@Html.EditorFor(model => model.Name, new { htmlAttributes = new { @id = "DonorFormName", @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Name, "", new { @class = "text-danger" })
</div>
</div>
<More Form Fields... />
</div>
}
我的 Parent 表单 (Items/Create.cshtml):
<script>
$(function () {
$("#DonorName").autocomplete({
source: '@Url.Action("Autocomplete")',
select: function (event, ui) {
$("#DonorId").val(ui.item.value);
$("#DonorName").val(ui.item.label);
return false;
},
focus: function (event, ui)
{
$("#DonorName").val(ui.item.label);
return false;
},
change: function (e, ui) {
if (!ui.item)
{
$("#dialog-form").load("@Url.Action("MinCreate", "Donors")", function () {
$("#DonorFormName").val(e.target.value);
dialog.dialog("open");
$("#DonorFormEmail").focus();
e.target.value = "";
});
}
}
});
var dialog = $("#dialog-form").dialog({
autoOpen: false,
width: 500,
height: 475,
dialogClass: "dialogStyle",
draggable: true,
resizable: false,
modal: true,
hide: { effect: "fade", duration: 1000 },
title: "New Donor",
open: function () {
$(this).closest(".ui-dialog")
.find(".ui-dialog-titlebar-close")
.html("<span class='ui-button-icon-primary ui-icon ui-icon-closethick'></span><span class='ui-button-text'>close</span>");
},
buttons: {
Submit: function () {
$.ajax({
url: "@Url.Action("MinCreate", "Donors")",
type: "POST",
data: $("#DonorForm").serialize(),
success: function (data) {
if (data.success) {
$("#dialog-form").dialog("close");
$("#DonorId").val(data.retObject.Id);
$("#DonorName").val(data.retObject.Name);
}
else {
$("#dialog-form").html(data);
}
}
});
return false;
},
}
});
$("#new-donor").click(function () {
$("#dialog-form").load("@Url.Action("MinCreate", "Donors")", function () {
dialog.dialog("open")
});
});
});
@using (Html.BeginForm()) {
<div class="form-horizontal" id="CreateItem">
<h4>Item</h4>
<hr />
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(model => model.Donor.Name, "Donor", htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Donor.Name, new { htmlAttributes = new { @class = "form-control", @id = "DonorName" } })<a href="#" id="new-donor">New Donor</a>
@*<input name="donor" class="control-label col-md-2" data-trf-autocomplete="@Url.Action("Autocomplete")" />*@
@Html.HiddenFor(model => model.DonorId, new { htmlAttributes = new { @id = "DonorId" } })
@Html.ValidationMessageFor(model => model.DonorId, "", new { @class = "text-danger" })
</div>
</div>
<More unimportant form fields... />
</div>
<div id="dialog-form"></div>
}
最后来自控制器的代码 Donors/MinCreate 动作:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult MinCreate([Bind(Include = "Id,Name,Email,AddressLine1,City,State,PostalCode,PrimaryPhone")] Donor donor)
{
try
{
if (ModelState.IsValid)
{
db.Donors.Add(donor);
db.SaveChanges();
var result = new { success = true, retObject = donor };
return Json(result, JsonRequestBehavior.DenyGet);
}
}
catch (Exception ex)
{
return Json(new { success = false, retObject = donor });
}
return PartialView("_Create", donor);
}
我知道这里可能有很多无用的废话,但我是 MVC 的新手,一个确切的例子正是我所需要的。所以,我希望有人觉得这很有用。