好的,这是交易,我在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进行验证时,验证就会消失。触发“重新绑定验证”警报,但$ .validator.unobtrusive.parse(“#frmAddItem”);似乎没有做任何事情。
任何人都可以帮助我缺少的东西吗?非常感谢。
&lt; =======================更新1 ==================== ======&GT;
好的,我尝试添加$ .validator.unobtrusive.parse(“#frmAddItem”);在文档就绪事件的局部视图的底部,它似乎也没有工作,基本上没有任何改变,我仍然可以提交表单。
我确实在这里找到了一个帖子:http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/提到当jqvalidation的MVC版本看到表单已经绑定了验证规则时,它只是忽略了.validator调用。我实现了这位绅士使用的脚本扩展,现在验证使用新扩展重新绑定到表单。我可以通过在表单中附加html并调用新扩展来测试它,然后重新绑定到新文本框。
然而,这仍然没有完全解决问题。我用Firebug查看了从ajax调用回来的字段的实际内容,并注意到一些非常奇怪的东西。
当我使用RenderPartial调用操作时,它会写出以下select:
<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">
我也尝试将脚本标记添加到局部视图中,但它没有解决问题。有没有理由说ajax调用会剥离不显眼的验证标签?
&lt; =======================更新2 ==================== ======&GT;
好的,所以发生的事情是,我有一个下拉列表的编辑器模板,它采用了一个选择列表并将其转换为html选择。我发现一篇帖子提到,为了在编辑器模板上写出数据验证属性,你必须有一个表单上下文。由于Html.RenderPartial是在表单中完成的,因此编辑器模板有一个表单上下文可供使用。当我只是试图通过ajax调用partial时,没有表单上下文可以使用,而不是抱怨它只是没有写出数据验证属性。在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();
}
}
答案 0 :(得分:71)
$.validator.unobtrusive.parse("#frmAddItem");
会奏效。请注意,它必须是通过ajax加载的部分(在部分中的表单下面)
<form id="frmAddItem" method="POST" action="...">
<!-- all the items -->
</form>
<script type="text/javascript">
$.validator.unobtrusive.parse("#frmAddItem");
</script>
答案 1 :(得分:8)
我正在添加我的经验,因为上述建议对我不起作用。 这个解决方案可以帮助其他人从搜索引擎转到此页面:
将OnSuccess="$.validator.unobtrusive.parse('YourFormName');"
添加到AjaxOptions
使用Ajax.ActionLink的示例:
@Ajax.ActionLink("This is a test to get unobtrusive javascript working",
"Name_of_your_controller_action",
new AjaxOptions { HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "UserDiv",
OnSuccess="$.validator.unobtrusive.parse('UserDetailsForm');"
}
)
答案 2 :(得分:7)
我写了这个小片段,你可以把它放在你的javascript文件中,它会处理所有你加载的ajax表单。
//enable unobtrusive validation for ajax loaded forms
$(document).ajaxSuccess(function (event, xhr, settings) {
//process only if html was returned
if ($.inArray('html', settings.dataTypes) >= 0) {
//will parse the element with given id for unobtrusive validation
function parseUnobtrusive(elementId) {
if (elementId) {
$.validator.unobtrusive.parse('#' + elementId);
}
}
//get the form objects that were loaded. Search within divs
//in case the form is the root element in the string
var forms = $('form', '<div>' + xhr.responseText + '</div>');
//process each form retrieved by the ajax call
$(forms).each(function () {
//get the form id and trigger the parsing.
//timout necessary for first time form loads to settle in
var formId = this.id;
setTimeout(function () { parseUnobtrusive(formId); }, 100);
});
}
});
答案 3 :(得分:4)
另一种选择,相当诡计,对我有用。只需在ajax调用返回的局部视图的开头添加以下行
this.ViewContext.FormContext = new FormContext();
答案 4 :(得分:1)
我只能在OnComplete
而不是OnSuccess
内进行验证:
这是AJAX代码:
@using (Ajax.BeginForm("Index", null,
new AjaxOptions { OnSuccess = "onSuccess",
OnComplete = "onComplete"},
new { id = "mainForm" }))
这是我的剧本:
function onComplete(result) {
$.validator.unobtrusive.parse("#mainForm");
alert("Complete");
};