2011-08-13 32 views
34

Ok, đây là thỏa thuận, tôi đã thấy một vài bài viết về SO liên quan đến vấn đề này, nhưng không có gì làm việc cho tôi.MVC3 Unobtrusive Validation Không hoạt động sau khi gọi Ajax

Về cơ bản, tôi đã chọn các trình đơn thả xuống đang được tải từ chế độ xem một phần, tôi đang cố gắng lọc nội dung của từng menu thả xuống tiếp theo, dựa trên menu thả xuống đã chọn trước đó.

Nếu tôi chỉ gọi điện đến chế độ xem một phần trong vùng chứa div và tải trang, xác thực từ chú thích dữ liệu hoạt động tốt, chủ yếu là thuộc tính Bắt buộc.

Tuy nhiên, nếu tôi cố gắng tải cùng một phần qua AJAX vì nó được thiết lập ở đây, xác nhận bắt buộc không hoạt động, bất kỳ ai cũng có thể đăng biểu mẫu sau đó và KABOOM.

Tôi đã tìm thấy mọi người nói rằng trong cuộc gọi lại thành công, bạn cần phải có trình xác nhận hợp lệ phía khách hàng sẽ xoá biểu mẫu, và tôi đang thử điều đó, nhưng dường như nó không hoạt động.

tôi có một cái nhìn mà trông như thế này ...

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

Lượt xem phần rất đơn giản, họ về cơ bản giống như thế này ...

@model Area51.Models.Workflow.AddReportableItemToBatchActionModel 

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

Một lần nữa, nếu tôi chỉ renderPartial , xác nhận hoạt động tốt, tuy nhiên khi tôi cố gắng làm điều đó thông qua ajax, việc xác nhận biến mất. Cảnh báo "Rebinding Validation" kích hoạt, nhưng $ .validator.unobtrusive.parse ("# frmAddItem"); dường như không làm gì cả.

Có ai có thể trợ giúp những gì tôi đang thiếu không? Nó sẽ được đánh giá rất cao.

< ======================= CẬP NHẬT 1 ==================== =========>

OK, tôi đã thử thêm $ .validator.unobtrusive.parse ("# frmAddItem"); ở dưới cùng của khung nhìn từng phần trong một sự kiện sẵn sàng tài liệu và nó dường như không hoạt động, hoặc về cơ bản không có gì thay đổi, tôi vẫn có thể gửi biểu mẫu.

Tôi đã tìm thấy một bài đăng ở đây: http://xhalent.wordpress.com/2011/01/24/applying-unobtrusive-validation-to-dynamic-content/ mà nói rằng khi phiên bản MVC của jqvalidation thấy một hình thức đã có quy tắc xác nhận bị ràng buộc vào nó, nó chỉ bỏ qua các cuộc gọi .validator. Tôi đã triển khai phần mở rộng tập lệnh mà quý ông này đã sử dụng, và việc xác nhận hợp lệ hiện đang được đưa vào biểu mẫu bằng cách sử dụng phần mở rộng mới. Tôi có thể kiểm tra điều này bằng cách nối thêm html vào biểu mẫu và gọi phần mở rộng mới, và nó được đưa vào hộp văn bản mới.

Tuy nhiên, điều này vẫn chưa khắc phục được sự cố. Tôi đã sử dụng Firebug để kiểm tra nội dung thực tế trên các trường quay lại từ cuộc gọi ajax và nhận thấy có điều gì đó rất lạ.

Khi tôi sử dụng renderPartial gọi hành động, nó viết ra các lựa chọn sau:

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

Tuy nhiên, khi tôi thực hiện cuộc gọi ajax để hành động điều khiển chính xác cùng, nó mang lại cho tôi trở lại này:

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

Tôi đã thử thêm thẻ tập lệnh vào chế độ xem một phần, nhưng nó không khắc phục được sự cố. Có một số lý do tại sao cuộc gọi ajax sẽ được tước các thẻ xác nhận không phô trương?

< ======================= CẬP NHẬT 2 ==================== =========>

Ok, vậy điều gì đã xảy ra, là tôi đã có mẫu trình chỉnh sửa cho trình đơn thả xuống danh sách lựa chọn và chuyển đổi nó thành lựa chọn html. Tôi tìm thấy một bài viết đã đề cập rằng để có được các thuộc tính xác nhận dữ liệu để viết ra trên một mẫu trình soạn thảo, bạn phải có một ngữ cảnh biểu mẫu. Kể từ khi Html.RenderPartial đã được thực hiện trong một biểu mẫu, sau đó trình soạn thảo mẫu có một bối cảnh biểu mẫu để làm việc với. Khi tôi chỉ cố gắng gọi một phần thông qua ajax, không có bối cảnh biểu mẫu nào để làm việc, và thay vì phàn nàn nó chỉ không viết ra các thuộc tính xác nhận dữ liệu. Thêm một bối cảnh mẫu mới trong mẫu trình soạn thảo cho SelectListDropDown đã khắc phục sự cố.

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

có thể trùng lặp của [Trouble nhận được xác thực không phô trương làm việc với mvc 3 trên jquery ajax bài] (http: //stackoverflow.com/questions/7005052/trouble-getting-unobtrusive-validation-working-with-mvc-3-on-jquery-ajax-post) – jgauffin

+0

Cũng trùng lặp với: http://stackoverflow.com/questions/6812779/mvc-3-dao cạo-tải-một phần-với-xác nhận – jgauffin

+1

Thêm các ViewContext.FormContext công cụ cố định vấn đề của tôi. – K0D4

Trả lời

67

$.validator.unobtrusive.parse("#frmAddItem"); sẽ hoạt động. Hãy lưu ý rằng nó phải ở một phần mà bạn tải thông qua ajax (dưới hình thức trong một phần)

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

Ok, sau khi chỉ thêm tập lệnh vào biểu mẫu ở cuối phần, aka: thay vì thử sự kiện sẵn sàng cho tài liệu, dường như nó hoạt động như mong đợi. Tôi đánh dấu câu trả lời này đúng, vì vấn đề với việc xác thực không đến thông qua ajax là một vấn đề riêng biệt.Cảm ơn nhiều jgauffin –

+0

+1 tuyệt vời, đã cho tôi lứa tuổi để tìm giải pháp cho vấn đề này – Liam

+9

Chỉ cần lưu ý, tôi đã thực hiện một cách tiếp cận hơi khác và thêm nó vào hàm thành công của cuộc gọi ajax của tôi '$ .ajax ({success: function () {$. validator.unobtrusive.parse ('form');}}); ' – Liam

8

Tôi đang thêm kinh nghiệm của tôi như các khuyến nghị trên đã không làm việc cho tôi. Giải pháp này đã và có thể giúp đỡ người khác mà có được dẫn đến trang này từ một công cụ tìm kiếm:

Thêm OnSuccess="$.validator.unobtrusive.parse('YourFormName');" cho bạn AjaxOptions

Một ví dụ sử dụng 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');" 
           } 
       ) 

Giải pháp này đã được tìm thấy tại: http://blog.janjonas.net/2011-07-24/asp_net-mvc_3-ajax-form-jquery-validate-supporting-unobtrusive-client-side-validation-and-server-side-validation

4

Một tùy chọn khác, thay vì lừa, đã làm việc cho tôi. Chỉ cần thêm dòng sau vào đầu quan điểm phần đó đang được trả lại bằng cách gọi ajax

this.ViewContext.FormContext = new FormContext(); 

Reference

+0

Ah, vì vậy bạn mới tạo ngữ cảnh biểu mẫu trong phần thay vì mẫu trình soạn thảo. Thành thật mà nói, mẫu có vẻ mô-đun hơn, vì nó sẽ hoạt động đối với bất kỳ cuộc gọi nào trên bất kỳ chế độ xem nào. Một điều bạn có thể muốn làm là kiểm tra xem ngữ cảnh có rỗng không trước khi bạn tạo một cái mới và ghi đè lên cái cũ ... –

+0

@DavidC Đi cho mẫu trình soạn thảo hoặc một phần, nó phụ thuộc vào kịch bản. Đối với trang đầu tiên tải ngữ cảnh không phải là null nhưng sau khi tất cả ajax gọi ngữ cảnh là null. Nó thực sự sẽ bị tổn thương nếu bối cảnh được thiết lập để mới ngay cả khi nó không phải là null? – bjan

+0

đúng là tùy thuộc vào kịch bản và cơ sở hạ tầng của bạn, một số người thậm chí không sử dụng các mẫu. Nhưng nếu bạn đi các tuyến đường mẫu nó IS mô-đun và khô hơn. Đối với câu hỏi thứ hai của bạn, tôi đoán nó sẽ phụ thuộc vào dữ liệu xác thực khác mà bối cảnh biểu mẫu có trước khi bạn dẫm lên nó. –

7

tôi đã viết đoạn này nhỏ mà sẽ giúp bạn có thể đặt trong file javascript của bạn và nó sẽ xử lý tất cả các bạn các biểu mẫu được tải 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); 
     }); 
    } 
}); 
+0

SetTimeout đã giúp tôi. Tôi ghét việc thêm những thứ như thế - có vẻ quá giòn. – Andy

+0

Bị bỏ qua vì setTimeout. Một cách tiếp cận xấu xí như vậy. –

+1

Chúng tôi downvote cho xấu xí? Được thăng hạng vì tôi thích bánh pudding. –

1

tôi chỉ có thể có được nó xác nhận để làm việc bên trong OnComplete thay vì OnSuccess:

Dưới đây là Bộ luật AJAX:

@using (Ajax.BeginForm("Index", null, 
         new AjaxOptions { OnSuccess = "onSuccess", 
             OnComplete = "onComplete"}, 
         new { id = "mainForm" })) 

Và đây là kịch bản của tôi:

function onComplete(result) { 
    $.validator.unobtrusive.parse("#mainForm"); 
    alert("Complete"); 
}; 
Các vấn đề liên quan