5

所以我有以下結構圖(這不是實際的代碼,但摘要):MVC客戶端驗證EditorFor中的foreach

@using (Html.BeginForm("Action", "Controller", FormMethod.Post)) 
{ 
    @Html.ValidationSummary("", new { @class = "text-danger" }) 
    <table> 
    <thead> 
     <tr> 
     <th>Column1</th> 
     <th>Column2</th> 
     </tr> 
    </thead> 
    <tbody id="myTableBody"> 
     @for (int i = 0; i < Model.Components.Count; i++) 
     { 
     @Html.EditorFor(m => m.MyCollection[i]) 
     } 
    </tbody> 
    <tfoot> 
     <tr> 
     <td> 
      <button id="btnAddRow" type="button">MyButton</button> 
     </td> 
     </tr> 
    </tfoot> 
    </table> 

    <input type="button" id="btnSubmit" /> 
} 

@section scripts { 
    @Scripts.Render("~/Scripts/MyJs.js") 
} 

的EditorFor被渲染的標記是表示綁定到MyCollection中的屬性的行。下面是編輯模板如何看起來示例代碼段:

@model MyProject.Models.MyCollectionClass 
 

 
<tr> 
 
    <td> 
 
    @Html.TextBoxFor(m => m.Name) 
 
    </td> 
 
    <td> 
 
    @Html.DropDownListFor(m => m.Type, Model.AvailableTypes) 
 
    </td> 
 
</tr>

基本上,我的問題是,它應該在客戶端驗證不會觸發要素編輯模板內。有人能指出我在哪裏可能會出錯的正確方向。

此外,請注意,以下是我的web.config中設置。

<appSettings> 
    <add key="ClientValidationEnabled" value="true" /> 
    <add key="UnobtrusiveJavaScriptEnabled" value="true" /> 
</appSettings> 

並且還MyCollectionClass有適當的[要求]對應被執行的屬性的註釋。另外需要注意的是,檢查

if(ModelState.IsValid) 
{ 
} 

如預期的那樣,如果所需字段不正確,則返回false。存在的問題是我想要客戶端驗證,而不是服務器端。我的其他頁面之一是實現jQuery驗證,但不包含此場景的所有嵌套,因此它可以正常工作。

在此先感謝。

+0

您是否添加了jQuery不引人注目的驗證腳本?我能看到頁面中包含的腳本嗎? – Giu

+3

刪除'for'循環 - 它只需要是'@ Html.EditorFor(m => m.MyCollection)'''EditorFor()'方法接受'IEnumerable '並且足夠聰明,集合中的每個項目。但是你的代碼沒有意義,因爲'for'循環是屬性'Components'不屬性'MyCollection'(是一個錯字嗎?) –

+3

在任何情況下,你應該爲每個屬性包含'@ Html.ValidationMessageFor()' 'EditorTemplate'使得用戶清楚哪一行有錯誤(並且摘要應該是@@ Html.ValidationSummary(true,「」,new {@class =「text-danger」})') –

回答

1

從我學到的MVC中不能真正提供'開箱即用'的客戶端驗證。 有第三方選項,但我更喜歡做我自己的事情,所以我用JavaScript編寫了整個事情。 若要使用EditorFor複合事項不允許添加像其他幫助方法一樣的HTML屬性。

我給這家修復是相當複雜的,但我覺得全面的,我希望你覺得它是有幫助我

首先過載的HtmlHelper EditorFor在.net

public static HtmlString EditBlockFor<T, TValue>(this HtmlHelper<T> helper, Expression<System.Func<T, TValue>> prop, bool required) 
    { 
     string Block = ""; 
     Block += "<div class='UKWctl UKWEditBox' " + 
      "data-oldvalue='" + helper.ValueFor(prop) + "' " + 
      "data-required='" + required.ToString() + ">"; 
     Block += helper.EditorFor(prop); 
     Block += "</div>"; 

     return new HtmlString(Block); 
    } 

添加新editBlockfor在Razor視圖(就像你),但改變形式開始的方法添加一個名稱和ID的表單元素,以便您可以識別它以後

@using (Html.BeginForm("Action", "Controller", FormMethod.Post, new { name = "MyDataForm", id = "MyDataForm" })) 

然後,當用戶點擊保存,從JavaScript運行驗證方法

function validate(container) { 

    var valid = true; 
    //use jquery to iterate your overloaded editors controls fist and clear any old validation 
    $(container).find(".UKWctl").each(function (index) { clearValidation($(this)); }); 
    //then itterate Specific validation requirements 
    $(container).find(".UKWctl[data-required='True']").each(function (index) { 
     var editobj = getUKWEdit(this); 
     if (editobj.val() == "") { 
      valid = false; 
      //use this Method to actually add the errors to the element 
      AddValidationError(editobj, 'This field, is required'); 
      //now add the Handlers to the element to show or hide the valdation popup 
      $(editobj).on('mouseenter', function (evt) { showvalidationContext(editobj, evt); }); 
      $(editobj).on('mouseout', function() { hidevalidationContext(); }); 
      //finally add a new class to the element so that extra styling can be added to indicate an issue 
     $(editobj).addClass('valerror'); 
    } 
    }); 
    //return the result so the methods can be used as a bool 
    return valid; 
} 

添加驗證方法

function AddValidationError(element, error) { 
    //first check to see if we have a validation attribute using jQuery 
    var errorList = $(element).attr('data-validationerror'); 
    //If not Create a new Array() 
    if (!errorList || errorList.length < 1) { 
     errorList = new Array(); 
    } else { 
     //if we have, parse the Data from Json 
     var tmpobj = jQuery.parseJSON(errorList); 
     //use jquery.Map to convert it to an Array() 
     errorList = $.map(tmpobj, function (el) { return el; }); 
    } 
    if ($.inArray(error, errorList) < 0) { 
     // no point in add the same Error twice (just in case) 
     errorList.push(error); 
    } 
    //then stringyfy the data backl to JSON and add it to a Data attribute  on your element using jQuery 
    $(element).attr('data-validationerror', JSON.stringify(errorList)); 
} 

最後顯示和隱藏實際的錯誤, 爲了方便這一點很容易我滑倒在一個小的div元素的_佈局。HTML

<div id="ValidataionErrors" title="" style="display:none"> 
     <h3 class="error">Validation Error</h3> 
     <p>This item contatins a validation Error and Preventing Saving</p> 
     <p class="validationp"></p> 
    </div> 

顯示

var tipdelay; 
function showvalidationContext(sender, evt) 
{ 
    //return if for what ever reason the validationError is missing 
    if ($(sender).attr('data-validationerror') == "") return; 
    //Parse the Error to an Object 
    var jsonErrors = jQuery.parseJSON($(sender).attr('data-validationerror')); 
    var errorString = ''; 
//itterate the Errors from the List and build an 'ErrorString' 
    for (var i = 0; i <= jsonErrors.length; i++) 
    { 
     if (jsonErrors[i]) { 
      //if we already have some data slip in a line break 
      if (errorString.length > 0) { errorString += '<br>'; } 
      errorString += jsonErrors[i]; 
     } 
    } 
//we don't want to trigger the tip immediatly so delay it for just a moment 
    tipdelay = setTimeout(function() { 
     //find the p tag tip if the tip element 
     var validationError = $('#ValidataionErrors').find('.validationp'); 
     //then set the html to the ErrorString 
     $(validationError).html(errorString); 
     //finally actually show the tip using jQuery, you can use the  evt to find the mouse position 
     $('#ValidataionErrors').css('top', evt.clientY); 
     $('#ValidataionErrors').css('left', evt.clientX); 
     //make sure that the tip appears over everything 
     $('#ValidataionErrors').css('z-index', '1000'); 
     $('#ValidataionErrors').show(); 
    }, 500); 
}  

隱藏(它更容易隱藏)

function hidevalidationContext() { 
    //clear out the tipdelay 
    clearTimeout(tipdelay); 
    //use jquery to hide the popup 
    $('#ValidataionErrors').css('top', '-1000000px'); 
    $('#ValidataionErrors').css('left', '-1000000px'); 
    $('#ValidataionErrors').css('z-index', '-1000'); 
    $('#ValidataionErrors').hide(); 
} 

的使用情況,您可以嘗試像

function save() 
{ 
    if (validate($("#MyDataForm"))) 
    { 
     $("#MyDataForm").submit(); 
    } 
    else { 
     //all the leg has been done this stage so perhaps do nothing 
    } 
} 

這裏有些事情是我的CSS用於驗證Popup

#ValidataionErrors { 
    display: block; 
    height: auto; 
    width: 300px; 
    background-color: white; 
    border: 1px solid black; 
    position: absolute; 
    text-align: center; 
    font-size: 10px; 
} 

#ValidataionErrors h3 { border: 2px solid red; } 
.valerror { box-shadow: 0 0 2px 1px red; }