2011-08-13 50 views
34

好的,這是交易,我已經看到有關此問題的SO上的一些帖子,但沒有任何工作適合我。MVC3不顯眼的驗證無法在Ajax調用後工作

基本上,我選擇了從部分視圖加載的下拉列表,我試圖根據之前選擇的下拉列表篩選每個後續下拉列表的內容。

如果我只是調用div容器中的部分視圖並加載頁面,那麼從數據註釋驗證工作正常,主要是必需屬性

但是,如果我嘗試通過AJAX加載與此處設置的相同的部分,則必需的驗證不起作用,任何人都可以在此之後發佈表單和KABOOM。

我發現有人說在成功回調中,你需要讓客戶端驗證器重新解析表單,並且我正在嘗試這樣做,但似乎沒有工作。

我有一個看起來像這樣的觀點...

@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」);似乎沒有做一件事情。

任何人都可以幫助我失去了什麼?這將不勝感激。

< =======================更新1 ==================== =========>

好的,我試着添加$ .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 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調用會剝離不顯眼的驗證標籤有什麼原因嗎?

< ======================= UPDATE 2 ==================== =========>

好了,發生了什麼事,是我曾經對自己採取了選擇列表,並將其轉換爲HTML選擇下拉編輯模板。我發現一篇文章提到爲了讓數據驗證屬性寫在編輯器模板上,你必須有一個表單上下文。由於Html.RenderPartial是在一個表單內完成的,編輯器模板有一個表單上下文來處理。當我只是試圖通過ajax調用部分內容時,沒有任何形式上下文可用,而不是抱怨它沒有寫出數據驗證屬性。在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

可能的重複[麻煩越來越不引人注目的驗證使用mvc 3在jquery ajax後](http: //stackoverflow.com/questions/7005052/trouble-getting-unobtrusive-validation-working-with-mvc-3-on-jquery-ajax-post) – jgauffin

+0

還複製的:http://stackoverflow.com/questions/6812779/MVC-3-剃刀負載局部與驗證 – jgauffin

+1

添加ViewContext.FormContext東西固定我的問題。 – K0D4

回答

67

$.validator.unobtrusive.parse("#frmAddItem");將工作。請注意,必須在局部,你可以通過AJAX(在部分下面的表格)加載

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

好的,在部分,又名的端部的形式添加剛好腳本後:<腳本類型=「文本/ JavaScript的」> $ .validator.unobtrusive.parse(「#frmAddItem」); 而不是嘗試文檔就緒事件,它似乎按預期工作。我正確地標記了這個答案,因爲在ajax上沒有通過驗證的問題是一個單獨的問題。感謝jgauffin –

+0

+1真棒,花了我很長時間才找到這個問題的解決方案 – Liam

+9

只需要注意,我採取了一個稍微不同的方法,並將其添加到我的ajax調用成功函數'$ .ajax({success:function( ){$。validator.unobtrusive.parse('form');}});' – Liam

8

我加入我的經驗,上述建議並沒有爲我工作。 該解決方案也並可能幫助別人是那些獲得指向此頁面的搜索引擎:

使用Ajax.ActionLink添加OnSuccess="$.validator.unobtrusive.parse('YourFormName');"你AjaxOptions

一個例子:

@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');" 
           } 
       ) 

該解決方案被發現在: 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

另一種選擇,而不是欺騙,這爲我工作。只需添加以下行正在由AJAX調用返回的局部視圖

this.ViewContext.FormContext = new FormContext(); 

Reference

+0

啊,所以你在部分而不是編輯器模板中創建了表單上下文。老實說,模板似乎更加模塊化,因爲它可以用於任何視圖上的任何呼叫。你可能想要做的一件事是在創建一個新文件之前檢查上下文是否爲空,並覆蓋舊的文件... –

+0

@DavidC尋找編輯器模板還是部分取決於場景。對於第一頁加載,上下文不爲空,但畢竟ajax調用上下文爲空。如果上下文設置爲新的,即使它不爲空,它是否真的會受到傷害? – bjan

+0

確實取決於場景和基礎設施,有些人甚至不使用模板。但是,如果你走模板路線,它更模塊化和乾燥。至於你的第二個問題,我想這將取決於在你踩踏它之前,表單上下文所具有的其他驗證數據。 –

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); 
     }); 
    } 
}); 
+0

setTimeout幫助我。我討厭添加這樣的東西 - 雖然看起來太脆弱了。 – Andy

+0

由於setTimeout而被降級。這樣一個醜陋的方法。 –

+1

我們贊成醜陋? Upvoted因爲我喜歡布丁。 – 2015-06-10 12:50:11

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"); 
}; 
相關問題