36 votos

MVC3 Discreta de Validación No funciona después de la Llamada Ajax

Ok, aquí está la oferta, he visto un par de posts en LO relativo a este tema, pero no hay nada de trabajo para mí.

Básicamente, he seleccione listas desplegables que se cargan de vistas parciales, estoy tratando de filtrar los contenidos de cada una de las siguientes desplegable, basado en la previamente seleccionada desplegable.

Si acabo de poner la llamada a la visión parcial en el div de los contenedores y de la carga de la página, la validación de datos de anotaciones funciona bien, Requiere principalmente de atributo.

Sin embargo, si intento cargar el mismo parcial a través de AJAX como es la instalación de aquí, la validación no funciona, cualquier persona puede publicar el formulario después de que y KABOOM.

He encontrado gente que dice que en el Éxito de devolución de llamada que usted necesita para tener el lado del cliente validador de reanálisis de la forma, y estoy tratando de que, pero no parece estar funcionando.

Tengo un punto de vista que se parece a esto...

  @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 sencillas, básicamente este aspecto...

@model Area51.Models.Workflow.AddReportableItemToBatchActionModel

      <hr />
          <h3>Select the Item to Add</h3>
          @Html.EditorFor(x => x.Item)
          <br />

De nuevo, si sólo me RenderPartial, la validación funciona bien, sin embargo cuando trato de hacerlo a través de ajax, la validación desaparece. La "Reconsolidación de la Validación de la" alerta de incendios, pero el $.validador.discreta.parse("#frmAddItem"); no parece estar haciendo una cosa.

Alguien puede ayudar con lo que me estoy perdiendo? Sería muy apreciado.

<======================= ACTUALIZACIÓN 1 =============================>

OK, he intentado añadir el $.validador.discreta.parse("#frmAddItem"); en la parte inferior de la vista parcial en un documento listo evento y no se parecía a trabajar, básicamente, nada ha cambiado, todavía podía enviar el formulario.

Encontré un post aquí : http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/ la que se menciona que cuando el MVC versión de la jqvalidation ve de una forma ya tiene reglas de validación enlazado a él, simplemente ignora el .validador de llamada. He implementado la secuencia de comandos de extensión que este señor utiliza, y la validación es ahora volver a vincular a la forma de usar la nueva extensión. Puedo probar esta anexando html para el formulario y llamar a la nueva extensión, y es que vuelve a enlazar con el nuevo cuadro de texto.

Sin embargo, esto aún no ha completamente solucionado el problema. He utilizado Firebug para retirar el contenido real en los campos de regresar de la llamada ajax, y se dio cuenta de que algo muy extraño.

Cuando yo uso el RenderPartial para llamar a la acción, escribe la siguiente instrucción 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">

Sin embargo, cuando hago la llamada ajax, exactamente la misma acción del controlador, se me da esto de nuevo :

<select id="Item" name="Item">

He intentado añadir las etiquetas de script para la vista parcial así, pero no soluciona el problema. ¿Hay alguna razón por la que la llamada ajax sería despojar a los discreta de validación de etiquetas?

<======================= ACTUALIZACIÓN 2 =============================>

Ok, así que lo que estaba sucediendo, es que tenía un editor de plantilla de la lista desplegable que se seleccione de la lista y se convierte en un html select. He encontrado un post en el que se menciona que con el fin de obtener la validación de datos de los atributos de escribir en un editor de plantilla, usted tiene que tener un formulario de contexto. Desde el Html.RenderPartial que se realiza dentro de un formulario, a continuación, el editor de plantilla tenía un formulario de contexto para trabajar con. Cuando yo estaba tratando de llamar a la parcial a través de ajax, no había forma de un contexto para trabajar con, y en lugar de quejarse de que no se escribe fuera de la validación de datos de atributos. Añadir un nuevo Formulario Contexto en el editor de plantillas para la SelectListDropDown solucionado 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();
    }
}

71voto

jgauffin Puntos 51913

$.validator.unobtrusive.parse("#frmAddItem"); de trabajo. Tenga en cuenta que debe ser en el parcial que se carga a través de ajax (debajo de la forma en el parcial)

<form id="frmAddItem" method="POST" action="...">
    <!-- all the items -->
</form>
<script type="text/javascript">
    $.validator.unobtrusive.parse("#frmAddItem");
</script>

8voto

user1079925 Puntos 193

Voy a agregar mi experiencia como las recomendaciones anteriores no me funciona. Esta solución se hizo y puede ayudar a otros que dirigirse a esta página de un motor de búsqueda:

Agregar OnSuccess="$.validator.unobtrusive.parse('YourFormName');" a usted AjaxOptions

Un ejemplo del uso de 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 encuentra 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

7voto

Alex Puntos 3871

Escribí este pequeño fragmento de código que se puede colocar en el archivo javascript y que se encargará de todos los formularios que se ajax carga.

//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);
        });
    }
});

4voto

bjan Puntos 781

Otra opción, en lugar truco, que trabajó para mí. Sólo añadir la siguiente línea al principio de la visión parcial que está siendo devuelto por la llamada ajax

this.ViewContext.FormContext = new FormContext(); 

Referencia

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X