27 votes

La validation discrète MVC3 ne fonctionne pas après un appel Ajax

Ok, voici le deal, j'ai vu quelques posts sur DONC, concernant cette question, mais rien ne fonctionne pour moi.

En gros, j'ai sélectionner des listes déroulantes qui sont chargés de vues partielles, je suis en train de filtrer le contenu de chaque menu déroulant, basé sur le précédemment sélectionné déroulant.

Si je viens de le mettre à l'appel de la vue partielle dans le div de conteneurs, et de charger la page, la validation à partir de données d'annotations fonctionne très bien, surtout attribut Nécessaire.

Cependant, si j'essaie de charger le même partielle via AJAX comme c'est le programme d'installation ici, la validation ne fonctionne pas, n'importe qui peut poster le formulaire à la suite et KABOOM.

J'ai trouvé des gens en disant que, dans le Succès de rappel, vous devez avoir le côté client du programme de validation d'analyse de la forme, et je suis en train d'essayer, mais il ne semble pas fonctionner.

J'ai une vision qui ressemble à ceci...

  @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>

Les Vues Partielles sont très simple, en fait, ils ressemblent à ça...

@model Area51.Models.Workflow.AddReportableItemToBatchActionModel

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

Encore une fois, si je viens de RenderPartial, la validation fonctionne bien, mais lorsque j'essaie de le faire via ajax, la validation s'en va. La "Reconsolidation de Validation" alerte se déclenche, mais le $.programme de validation.discrète.parse("#frmAddItem"); ne semble pas être en train de faire une chose.

N'importe qui peut aider avec ce que je suis absent? Il serait grandement apprécié.

<======================= Mise à JOUR 1 =============================>

OK, j'ai essayé d'ajouter le $.programme de validation.discrète.parse("#frmAddItem"); au bas de la vue partielle dans un document prêt et il ne semble pas fonctionner non plus, fondamentalement, rien n'a changé, je pourrais toujours envoyer le formulaire.

J'ai trouvé un post ici : http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/ que mentionné que lorsque le MVC version de la jqvalidation voit un formulaire a déjà des règles de validation lié à elle, il ignore juste les .programme de validation d'appel. J'ai mis en place le script de l'extension que ce monsieur utilisé, et la validation est maintenant une nouvelle liaison de la forme à l'aide de la nouvelle extension. Je peux le tester en ajoutant html pour la forme et l'appel de la nouvelle extension, et c'est une nouvelle liaison vers la nouvelle zone de texte.

Toutefois, cela n'a pas complètement résolu le problème. J'ai utilisé Firebug pour vérifier le contenu actuel sur les champs de retour de l'appel ajax, et a remarqué quelque chose de très étrange.

Lorsque j'utilise le RenderPartial appel à l'action, il écrit la sélection suivante :

<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">

Cependant, quand je fais l'appel ajax, exactement la même action de contrôleur, il me donne ce retour :

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

J'ai essayé d'ajouter les balises de script de la vue partielle, mais il n'a pas de résoudre le problème. Est-il une raison pour laquelle l'appel ajax serait le décapage de la discrète validation des balises?

<======================= Mise à JOUR 2 =============================>

Ok, donc ce qui se passait, est j'ai eu un éditeur de modèle pour la liste déroulante, qui a eu une liste de sélection et l'a converti en html, sélectionnez. J'ai trouvé un post qui a indiqué qu'afin d'obtenir la validation des données d'attributs d'écrire sur un éditeur de modèle, vous devez avoir un formulaire de contexte. Depuis le Html.RenderPartial a été fait dans un formulaire, puis l'éditeur de template de un formulaire contexte de travailler avec. Quand j'essayais juste d'appeler la partielle via ajax, il n'y a pas de formulaire contexte de travailler avec, et au lieu de se plaindre, il n'a tout simplement pas écrire les données d'attributs de validation. L'ajout d'une nouvelle Forme de Contexte dans l'éditeur de modèle pour la SelectListDropDown résolu le problème.

@{ // fix to stop stupid crappy brad wilson mvc3 code from stripping the jq data valdiation attributes
    if (ViewContext.FormContext == null)
    {
        ViewContext.FormContext = new FormContext();
    }
}

51voto

jgauffin Points 51913

$.validator.unobtrusive.parse("#frmAddItem"); fonctionnera. Notez qu'il doit être dans le partiel que vous chargez via ajax (sous le formulaire dans le partiel)

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

8voto

user1079925 Points 193

Je vais ajouter mon expérience que les recommandations ci-dessus ne fonctionne pas pour moi. Cette solution n'a et peut aider d'autres qui sont dirigées vers cette page à partir d'un moteur de recherche:

Ajouter OnSuccess="$.validator.unobtrusive.parse('YourFormName');" vous AjaxOptions

Un exemple d'utilisation de l'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');"  
                                 }
                )

Cette solution a été trouvé à: http://blog.janjonas.net/2011-07-24/asp_net-mvc_3-ajax-form-jquery-validate-supporting-unobtrusive-client-side-validation-and-server-side-validation

5voto

Alex Points 3871

J'ai écrit ce petit extrait que vous pourrez placer dans votre fichier javascript et il gérera tous vos formulaires qui sont chargés en 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);
        });
    }
});
 

4voto

bjan Points 781

Une autre option, plutôt astuce, qui a fonctionné pour moi. Ajoutez simplement la ligne suivante au début de la vue partielle qui est retournée par l'appel ajax

 this.ViewContext.FormContext = new FormContext(); 
 

Référence

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X