Создать дочерний объект, используя диалог jQuery / частичное представление
Я использую MVC 5/ JQuery 1.10.2 и JQuery UI 1.11.3
Для этого примера у меня есть родительский объект с одним дочерним объектом. В представлении "Создать" для родительского объекта у меня есть текстовое поле автозаполнения, из которого пользователь выбирает одного из дочерних объектов. Если дочерний элемент еще не существует, пользователь может щелкнуть ссылку, которая открывает диалоговое окно 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")
});
});
});
Теперь у меня есть две проблемы:
- Когда я успешно отправляю форму частичного представления, я хочу закрыть диалоговое окно и вернуть вновь созданные дочерние данные в существующую родительскую форму. Я понятия не имею, как это сделать.
- Если при частичном просмотре на стороне сервера происходит сбой проверки, я хочу явно вернуть сбой в существующее диалоговое окно. В настоящее время он будет перенаправлен на частичное представление.
Мой частичный код просмотра здесь:
@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);
}
2 ответа
Итак, мне потребовалось несколько дней, чтобы обдумать эту проблему, и я думаю, что Скури, возможно, пытался указать мне в этом направлении. Ниже приведено решение, которое я придумала:
- Мне пришлось инициировать весь код JavaScript из родительского представления.
- Я использовал форму Ajax в части и использовал кнопку диалога "Submit" для вызова $.ajax и отправки данных формы и определения события "success".
- Событие успеха проверяет возвращаемое значение из контроллера, и если я устанавливаю retObject.success == true, то оно находит значения в родительской форме и устанавливает имя и идентификатор донора, и я закрываю диалоговое окно jQuery.
- Если retObject.success имеет значение null, то я знаю, что вернул Invalid ModelState, поэтому я устанавливаю это возвращаемое значение для свойства диалоговых форм.html, используя селектор jQuery.
Я понимаю, вероятно, 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>
}
Моя родительская форма (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, и точный пример - это то, что мне нужно. Итак, я надеюсь, что кто-то найдет это полезным.
JQuery кажется лучшим способом сделать это; помощники Razor Ajax всегда кажутся мне неуклюжими.
Прежде чем перейти к этой части, взгляните на свою часть; в то время как у вас есть элемент div, класс которого настроен на форму по горизонтали, у вас фактически нет формы в частичном представлении. Либо используйте помощник Razor @using (Html.BeginForm(....))
или добавьте форму с <form name="this_form" id="this_form" method="post">
Если вы правильно настроили форму, вы можете добавить Javascript к вашему частичному представлению и использовать jQuery для отправки формы, а затем, при успешном размещении формы, вы можете сделать $.get() для обновления содержимого родительской формы или, если сообщение терпит неудачу, делай что-то еще
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...
})