Хорошо, вот сделка, я видел несколько сообщений по SO, относящихся к этой проблеме, но для меня ничего не работает.
В принципе, у меня есть выпадающие списки, которые загружаются из частичных представлений, я пытаюсь фильтровать содержимое каждого последующего выпадающего списка на основе ранее выбранного раскрывающегося списка.
Если я просто поместил вызов в частичный вид в контейнерах div и загрузил страницу, проверка аннотаций данных прекрасна, в первую очередь обязательный атрибут.
Однако, если я попытаюсь загрузить тот же частичный через AJAX, как он здесь установлен, обязательная проверка не работает, каждый может опубликовать форму после этого и KABOOM.
Я нашел людей, говорящих, что в обратном вызове Success вам нужно, чтобы валидатор на стороне клиента повторно обработал форму, и я пытаюсь это сделать, но он, похоже, не работает.
У меня есть вид, который выглядит так...
@model Area51.Models.Workflow.AddReportableItemToBatchActionModel
@{
ViewBag.Title = "Add Reportable Item to Batch";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script type="text/javascript">
$(function () {
var fadeDelay = 150;
$(".jqDatePicker").datepicker({
dateFormat: 'm/d/yy',
onSelect: function (date) {
$("#categoryContainer").show(fadeDelay);
}
});
$('#Category').change(function () {
RetrieveItemsForCategory();
$("#itemContainer").show(100);
});
$('#Item').live('change', function () {
RenderPartialForUOMByItem();
});
function RetrieveItemsForCategory() {
var category = $("#Category :selected").val();
$.ajax({
type: "POST",
url: '@Url.Action("RenderPartialForLocationItemsByCategory","BatchWorkflow")',
data: 'category=' + category,
success: function (result) {
$("#itemContainer").html(result.toString());
$("#itemContainer").show(100);
RebindValidation();
},
error: function (req, status, error) {
alert("Sorry! Could not request items for your selection at this time.");
}
});
}
function RenderPartialForUOMByItem() {
var item = $("#Item :selected").val();
$.ajax({
type: "POST",
url: '@Url.Action("RenderPartialForUOMByItem","BatchWorkflow")',
data: "item=" + item,
success: function (result) {
$("#quantityContainer").html(result.toString());
$("#quantityContainer").show(100);
RebindValidation();
},
error: function (req, status, error) {
alert("Sorry! Could not request items for your selection at this time.");
}
});
}
function RebindValidation() {
alert("Rebinding Validation");
$.validator.unobtrusive.parse("#frmAddItem");
}
}); // End OnLoad Event
</script>
<h3 class="pageHeader">Batch : @Model.BatchName</h3>
<div align="center">
@{Html.BeginForm("AddItemToBatch", "BatchWorkflow", null, FormMethod.Post, new { id = "frmAddItem" });}
@Html.ValidationSummary(true)
<fieldset style="width:60%">
<legend>Add an Item to the Batch</legend>
<div>
<h3>Select Date Item was Added</h3>
@Html.EditorFor(x => x.EventDate,null)
<br />
</div>
<div id="categoryContainer" style="display:none">
<hr />
<h3>Select an Inventory Category</h3>
@Html.EditorFor(x => x.Category,null)
<br />
</div>
<div id="itemContainer" style="display:none">
@* @{Html.RenderAction("RenderPartialForLocationItemsByCategory", "BatchWorkflow", new { category = Model.Category });}*@
</div>
<div id="quantityContainer" style="display:none">
@* @{Html.RenderAction("RenderPartialForUOMByItem", "BatchWorkflow", new { item = Model.Item });}*@
</div>
<div id="reportingDataContainer" style="display:none">
<hr />
<h3>What quantity of the batch was affected by this addition?</h3>
@Html.EditorFor(x => x.ConsumedWineQuantity) (Gallons)
<br />
<hr />
<h3>What was the increase in Batch Volume as a result of this addition?</h3>
@Html.EditorFor(x => x.ProducedWineQuantity) (Gallons)
</div>
<div style="display:block">
<div></div>
<span><button type="button" id="btnCancel" class="linkButton" value="Cancel" onclick="location.href='@Url.Action("Home","Home",null)';">Cancel</button></span>
<span><button type="submit" id="btnSubmit" class="linkButton" value="Add">Add Item</button></span>
</div>
</fieldset>
@{ Html.EndForm(); }
</div>
Частичные представления очень просты, они в основном выглядят так...
@model Area51.Models.Workflow.AddReportableItemToBatchActionModel
<hr />
<h3>Select the Item to Add</h3>
@Html.EditorFor(x => x.Item)
<br />
Опять же, если я просто RenderPartial, проверка корректно работает, однако, когда я пытаюсь сделать это с помощью ajax, проверка продолжается. Предупреждение "Rebinding Validation" срабатывает, но $.validator.unobtrusive.parse( "# frmAddItem" ); похоже, ничего не делает.
Может ли кто-нибудь помочь с тем, что мне не хватает? Было бы очень благодарно.
< ======================== ОБНОВЛЕНИЕ 1 ==================== ========= >
Хорошо, я попробовал добавить $.validator.unobtrusive.parse( "# frmAddItem" ); в нижней части частичного представления в документе, готовом к событию, и он, похоже, тоже не работал, в основном ничего не изменилось, я все равно мог отправить форму.
Я нашел здесь сообщение: http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/, в котором упоминалось, что когда MVC-версия jqvalidation видит, что форма уже имеет правила проверки, связанные с ней, это просто игнорирует вызов .validator. Я внедрил расширение script, которое использовал этот джентльмен, и теперь валидация привязана к форме с использованием нового расширения. Я могу проверить это, добавив html в форму и вызвав новое расширение, и он переписывается в новое текстовое поле.
Однако это еще не полностью устранило проблему. Я использовал Firebug, чтобы проверить фактическое содержимое на полях, возвращающихся из вызова ajax, и заметил что-то очень странное.
Когда я использую RenderPartial для вызова действия, он выписывает следующий выбор:
<select id="Item" name="Item" data-val-required="The Item field is required." data-val-number="The field Item must be a number." data-val="true">
Однако, когда я делаю вызов ajax тому же правильному действию контроллера, он возвращает мне это:
<select id="Item" name="Item">
Я также попытался добавить теги script к частичному представлению, но это не устранило проблему. Есть ли причина, по которой вызов ajax будет лишать ненавязчивые теги проверки?
< ======================== ОБНОВЛЕНИЕ 2 ==================== ========= >
Хорошо, так что случилось, у меня был шаблон редактора для раскрывающегося списка, который взял список выбора и преобразовал его в html select. Я нашел сообщение, в котором упоминалось, что для того, чтобы получить атрибуты проверки данных для записи в шаблоне редактора, у вас должен быть контекст формы. Поскольку Html.RenderPartial выполнялся в форме, тогда шаблон редактора имел контекст формы для работы. Когда я просто пытался вызвать частичное через ajax, не было никакого контекста формы для работы, и вместо того, чтобы жаловаться, он просто не выписывал атрибуты проверки данных. Добавление нового контекста формы в шаблон редактора для SelectListDropDown устранило проблему.
@{ // fix to stop stupid crappy brad wilson mvc3 code from stripping the jq data valdiation attributes
if (ViewContext.FormContext == null)
{
ViewContext.FormContext = new FormContext();
}
}