Я очень новичок в MVC Razor (как и вся наша команда). Мой вопрос: как Ajaxify Partial view, но только если Razor HtmlValidationMessagefor проверил, что должно, затем вызов ajax.
Приведенный ниже код разрешает вызов ajax, даже если ничего не было выбрано из DDL (который имеет атрибут проверки.), И сделать это снова, и произошел сбой. Он теряет свою модель.
Мы полностью потерялиare.
Parent Host.cshtml
@model ReloadPartials.Models.MyContainer
@{
ViewBag.Title = "Host";
}
<div class="form-horizontal" id="divHost">
<h2>Host</h2>
@using (Html.BeginForm("Host", "Example"))
{
@Html.AntiForgeryToken()
@Html.Partial("Header", Model)
@Html.Partial("Details", Model)
<div id="divFooter" />
<div class="form-group">
<input type="submit" name="actionPerformed" value="Save All" class="btn btn-default col-md-offset-2 col-md-2" />
</div>
}
</div>
@section Scripts {
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/jqueryval")
}
Подробности cshtml
@model ReloadPartials.Models.MyContainer
@{
ViewBag.DetailIndex = 0;
int detailItemsSideBySide = 2;
int currentDetailItem = 1;
int i = 0;
}
<div class="form-horizontal" id="divDetails">
<h2>Details Section</h2>
@*@for (int i = 0; i < Model.Details.Count(); i++)
{*@
Model.Details[i].Index = i;
ViewBag.DetailIndex = i;
<div id="@("divDetails_"+i)">
@Html.Partial("Detail", Model)
</div>
if (currentDetailItem == detailItemsSideBySide)
{
currentDetailItem = 0;
<div id="divFooter" />
}
currentDetailItem++;
@*}*@
</div>
Detail.cshtml (внутренний единственный (или несколько экземпляров этого частичного представления, в зависимости от Details.cshtml)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function ()
{
$("#btnReload" + @ViewBag.DetailIndex).on("click", function ()
{
alert("ajax ... " + @ViewBag.DetailIndex);
var val = $('#txtInput'+@ViewBag.DetailIndex).val();
var ModelData = $('form').serialize();
$.ajax({
url: "/Example/GetAjaxPostBackData_OnlyTextBox",
type: "GET",
data: { ajaxDetailModelData: ModelData, index: @ViewBag.DetailIndex}
,
async: false
//contentType: "application/json; charset=utf-8",
//dataType: "json"
})
.done(function (partialViewResult)
{
alert("ajax done " + @ViewBag.DetailIndex);
//This replaces the Partial in the Div, with the new partial
$('#divDetails_' +@ViewBag.DetailIndex).replaceWith(partialViewResult);
});
});
});
</script>
@model ReloadPartials.Models.MyContainer
@{
int index = ViewBag.DetailIndex;
}
<div class="form-horizontal" id="divDetail">
<h2>Detail Section @index.ToString()</h2>
@Html.HiddenFor(model => model.Details[index].HeaderId)
@Html.HiddenFor(model => model.Details[index].Id)
<div class="form-group" id="ddlDiv">
@Html.LabelFor(model => model.Details[index].Name, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@*This on change will call submit*@
@*@Html.DropDownListFor(model => model.Details[index].Name, (SelectList)ViewBag.Names, "Select a Name", htmlAttributes: new { @class = "form-control", onchange = "$(this.form).submit();" })*@
@Html.DropDownListFor(model => model.Details[index].Name,
(SelectList)ViewBag.Names, "Select a Name",
htmlAttributes: new { @class = "form-control" , id = "ddlNames" + index.ToString() })
@Html.ValidationMessageFor(model => model.Details[index].Name, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group" id="txtInpDiv">
@Html.LabelFor(model => model.Details[index].SomeNumber, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.EditorFor(model => model.Details[index].SomeNumber,
new { htmlAttributes = new { @class = "form-control", id = "txtInput" + index.ToString() } })
@Html.ValidationMessageFor(model => model.Details[index].SomeNumber, "", new { @class = "text-danger" })
<p>@Model.Details[index].SomeNumber.ToString()</p>
</div>
<div id="BottomDiv"></div>
</div>
@*This button (and/or combo onchange) should actually go get data from the server and then just reload this detail section using AJAX*@
@*Use razor and the viewbag to uniquely identify each instance of this partial, such that we can identify which instance of this partial invoked the Ajax call*@
<div class="form-group">
<button id ="@("btnReload" + @ViewBag.DetailIndex)" name="actionPerformed" value="Reload Detail"
class="btn btn-default col-md-offset-2 col-md-3">Reload</button>
</div>
</div>
Контроллер
public class ExampleController : Controller
{
[ChildActionOnly]
private MyContainer InitialiseContainer()
{
MyContainer containter = new MyContainer();
containter.Header = new MyHeader(1, "Header Name");
containter.Details.Add(new MyDetail(1, 1, "Detail 1 Name", 100));
containter.Details.Add(new MyDetail(1, 2, "Detail 2 Name", 200));
return containter;
}
[HttpGet]
public ActionResult Host()
{
//ViewBag.xxSelectedItem = "Detail Name 4";
Session["isAjaxCall"] = false;
MyContainer container = InitialiseContainer();
ViewBag.Names = NamesLookup(null);
return View(container);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Host(MyContainer container, string actionPerformed)
{
if (actionPerformed == "Save All")
{
//return RedirectToAction("xxx");
}
if (actionPerformed == "Reload Detail")
{
if ((bool)Session["isAjaxCall"] == true)
{
ViewBag.DetailIndex = 0;
ViewBag.Names = NamesLookup(null);
NewModelContainer = (MyContainer)Session["MyContainer"];
return PartialView("Detail", NewModelContainer);
}
else
{
//this action runs if , from the ajax code we reference the Div(s) set by the parent view "Details"
container = setsomeValues(container);
ViewBag.DetailIndex = 0;
ViewBag.Names = NamesLookup(null);
return View(container);
}
}
ViewBag.Names = NamesLookup(null);
return View(container);
}
`public PartialViewResult GetAjaxPostBackData_OnlyTextBox(string ajaxDetailModelData, string index)
{
Session["isAjaxCall"] = true;
int i = 0;
int.TryParse(index, out i);
ViewBag.DetailIndex = i;
//get the items to populate the dropdown List with
ViewBag.Names = NamesLookup(null);
//get an instance of the Model (Container), either from session (with changed and persisted values in it, or Cleanly re-initialized)
MyContainer NewModelContainer = InitialiseContainer();
NewModelContainer = UnpackAjaxdetailModelData(ajaxDetailModelData,index);
//arb Test ..change the HTML Input
NewModelContainer.Details[i].SomeNumber = 777;
Session["NewModelContainer"] = NewModelContainer;
//return just the partial view as indexed, which's btnXXX_index was clicked
return PartialView("Detail", NewModelContainer);
}
[ChildActionOnly]
private SelectList NamesLookup(object selectedObject)
{
List<MyName> names = new List<MyName>();
names.Add(new MyName(1, "Detail Name 1"));
names.Add(new MyName(2, "Detail Name 2"));
names.Add(new MyName(3, "Detail Name 3"));
names.Add(new MyName(4, "Detail Name 4"));
names.Add(new MyName(5, "Detail Name 5"));
return new SelectList(names, "Name", "Name", selectedObject);
}
}
спасибо
Макет