c# - two - ultimate marvel vs capcom 3 pc
La validaciĆ³n discreta de MVC3 no funciona despuĆ©s de la llamada Ajax (5)
Ok, este es el trato, he visto algunas publicaciones sobre SO relacionadas con este tema, pero nada funciona para mí.
Básicamente, tengo selecciones desplegables que se están cargando desde vistas parciales, estoy tratando de filtrar los contenidos de cada menú desplegable posterior, en función del menú desplegable previamente seleccionado.
Si simplemente pongo la llamada a la vista parcial en los contenedores div y cargo la página, la validación de las anotaciones de datos funciona bien, principalmente el atributo Requerido .
Sin embargo, si intento cargar el mismo parcial a través de AJAX como está configurado aquí, la validación requerida no funciona, cualquiera puede publicar el formulario después de eso y KABOOM.
He encontrado personas que dicen que en la devolución de llamada de Success necesitas que el validador del lado del cliente vuelva a rastrear el formulario, y lo estoy intentando, pero parece que no funciona.
Tengo una vista que se ve así ...
@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>
Las vistas parciales son muy simples, básicamente se ven así ...
@model Area51.Models.Workflow.AddReportableItemToBatchActionModel
<hr />
<h3>Select the Item to Add</h3>
@Html.EditorFor(x => x.Item)
<br />
De nuevo, si acabo de RenderPartial, la validación funciona bien, sin embargo, cuando intento hacerlo a través de ajax, la validación desaparece. Se activa la alerta "Volver a vincular validación", pero el $ .validator.unobtrusive.parse ("# frmAddItem"); no parece estar haciendo nada.
¿Alguien puede ayudarme con lo que me estoy perdiendo? Podria ser muy apreciado.
<======================= ACTUALIZACIÓN 1 ======================== =====>
OK, traté de agregar $ .validator.unobtrusive.parse ("# frmAddItem"); en la parte inferior de la vista parcial en un evento listo para documentos y tampoco parecía funcionar, básicamente nada cambió, aún podía enviar el formulario.
Encontré una publicación aquí: http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/ que mencionaba que cuando la versión MVC de la versión jqvalidation considera que un formulario ya tiene reglas de validación vinculadas a él, simplemente ignora la llamada .validator. Implementé la extensión de script que este caballero usó, y la validación ahora se vuelve a vincular al formulario con la nueva extensión. Puedo probar esto al agregar html al formulario y al llamar a la nueva extensión, y se vuelve a vincular al nuevo cuadro de texto.
Sin embargo, esto aún no ha solucionado completamente el problema. Usé Firebug para verificar el contenido real en los campos que regresaban de la llamada ajax, y noté algo muy extraño.
Cuando utilizo RenderPartial para llamar a la acción, escribe lo siguiente:
<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">
Sin embargo, cuando hago la llamada ajax a la misma acción de controlador exacto, me da esto de nuevo:
<select id="Item" name="Item">
Traté de agregar las etiquetas de script a la vista parcial también, pero no solucionó el problema. ¿Hay alguna razón por la cual la llamada ajax sería quitar las etiquetas de validación discretas?
<======================= ACTUALIZACIÓN 2 ======================== =====>
Ok, entonces, ¿qué estaba pasando? ¿Tenía una plantilla de editor para el menú desplegable que tenía una lista de selección y la convertía a una selección html? Encontré una publicación que mencionaba que para que los atributos de validación de datos se escriban en una plantilla de editor, debe tener un contexto de formulario. Como Html.RenderPartial se estaba haciendo dentro de un formulario, la plantilla del editor tenía un contexto de formulario para trabajar. Cuando estaba tratando de llamar al parcial a través de ajax, no había un contexto de formulario con el que trabajar, y en lugar de quejarse, simplemente no escribía los atributos de validación de datos. Agregar un nuevo contexto de formulario en la plantilla del editor para SelectListDropDown solucionó el problema.
@{ // fix to stop stupid crappy brad wilson mvc3 code from stripping the jq data valdiation attributes
if (ViewContext.FormContext == null)
{
ViewContext.FormContext = new FormContext();
}
}
Escribí este pequeño fragmento que puede colocar en su archivo javascript y manejará todos sus formularios que están cargados ajajax.
//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);
});
}
});
Estoy agregando mi experiencia ya que las recomendaciones anteriores no me funcionaron. Esta solución fue y puede ayudar a otros que se dirigen a esta página desde un motor de búsqueda:
Agregue OnSuccess="$.validator.unobtrusive.parse(''YourFormName'');"
para ti AjaxOptions
Un ejemplo usando 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'');"
}
)
Esta solución se encontró en: http://blog.janjonas.net/2011-07-24/asp_net-mvc_3-ajax-form-jquery-validate-supporting-unobtrusive-client-side-validation-and-server-side-validation
Otra opción, más bien truco, que funcionó para mí. Simplemente agregue la siguiente línea al principio de la vista parcial que está siendo devuelta por una llamada ajax
this.ViewContext.FormContext = new FormContext();
Solo pude obtener la validación para trabajar dentro de OnComplete
lugar de OnSuccess
:
Aquí está el código AJAX:
@using (Ajax.BeginForm("Index", null,
new AjaxOptions { OnSuccess = "onSuccess",
OnComplete = "onComplete"},
new { id = "mainForm" }))
Y aquí está mi guión:
function onComplete(result) {
$.validator.unobtrusive.parse("#mainForm");
alert("Complete");
};
$.validator.unobtrusive.parse("#frmAddItem");
trabajará. Tenga en cuenta que debe estar en el parcial que carga a través de ajax (debajo del formulario en el parcial)
<form id="frmAddItem" method="POST" action="...">
<!-- all the items -->
</form>
<script type="text/javascript">
$.validator.unobtrusive.parse("#frmAddItem");
</script>