eik*_*kaz 4 css validation asp.net-mvc jquery
我有一个表有一行动态文本框.示例如下:

我通过单击[+]添加新目标在表格中添加行,它将出现在屏幕下方:

我想将验证类添加到表格内的所有文本框中.因此,当用户单击"保存"按钮时,它将检查所有文本框.
我尝试使用这个jquery:
 $('#tbTargetDetails tr').each(function () {
            $(this).find('td input:text').each(function (i,a) {
                // get each of the textbox and add validation class to it
            });
        });
我正在使用MVC 5,jquery-1.10.2.js,jquery-1.10.2.min.js,jquery.validate*和Site.css,它们具有类input.input-validation-error
在我的模特中:
 public class ClsTargetInfo
    {
        public string ItemNumber_Target { get; set; }
        [Required]
        public string TargetColor_U { get; set; }
        [Required]
        public string TargetColor_V { get; set; }
        [Required]
        public string D90Target_U { get; set; }
        [Required]
        public string D90Target_V { get; set; }
        [Required]
        public string D10Target_U { get; set; }
        [Required]
        public string D10Target_V { get; set; }
        [Required]
        public string Thickness { get; set; }
        [Required]
        public string FilmWidth { get; set; }
        [Required]
        public string TargetDate { get; set; }
    }
我在另一个模型中调用上面的模型:
public class abc
{
 public IList<ClsTargetInfo> TargetInfo { get; set; }
}
下面是我添加新行时的代码:
        $("#btnAddTarget").on("click", function (event) {
            AddTargetItem(jQuery('#txtTargetColorU').val(), jQuery('#txtD90TargetU').val(), jQuery('#txtD10TargetU').val(),
                           jQuery('#txtTargetColorV').val(), jQuery('#txtD90TargetV').val(), jQuery('#txtD10TargetV').val(),
                            jQuery('#txtThickness').val(), jQuery('#txtFilmWidth').val(), jQuery('#TargetDate').val());
});
function AddTargetItem(TargetColor_U, D90Target_U, D10Target_U, TargetColor_V, D90Target_V, D10Target_V, Thickness, FilmWidth, TargetDate) {
        var rowCount = $('#tbTargetDetails tr').length;
        //minus 1 row for header
        rowCount = rowCount - 2;
        var rowCountBil = rowCount + 1;
        var row = '<tr style="background-color:#ffffff;" id="tr_' + rowCount + '">';
        row += '<td style="font-weight:bold;padding-left:5px;padding-top:0px;padding-bottom:0px;padding-right:0px;vertical-align:middle">' + rowCountBil + '</td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__TargetColor_U" name="TargetInfo[' + rowCount + '].TargetColor_U" type="text" value="' + TargetColor_U + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__TargetColor_V" name="TargetInfo[' + rowCount + '].TargetColor_V" type="text" value="' + TargetColor_V + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__D90Target_U" name="TargetInfo[' + rowCount + '].D90Target_U" type="text" value="' + D90Target_U + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__D90Target_V" name="TargetInfo[' + rowCount + '].D90Target_V" style="text-align:center;" type="text" value="' + D90Target_V + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__D10Target_U" name="TargetInfo[' + rowCount + '].D10Target_U" style="text-align:center;" type="text" value="' + D10Target_U + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__D10Target_V" name="TargetInfo[' + rowCount + '].D10Target_V" style="text-align:center;" type="text" value="' + D10Target_V + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__Thickness" name="TargetInfo[' + rowCount + '].Thickness" style="text-align:center;" type="text" value="' + Thickness + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__FilmWidth" name="TargetInfo[' + rowCount + '].FilmWidth" style="text-align:center;" type="text" value="' + FilmWidth + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"><input class="form-control" id="TargetInfo_' + rowCount + '__TargetDate" name="TargetInfo[' + rowCount + '].TargetDate" style="text-align:center;" type="text" value="' + TargetDate + '" /></td>';
        row += '<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px;vertical-align:top;"><img id="imgRemoveTarget" alt="Item Lookup" src="/Content/images/trashcan.png" style="cursor:pointer;width:32px;height:29px;" class="deleteLink" /></td>';
        row += '</tr>';
        //Hide the previous delete button
        $('#tbTargetDetails tr:last .deleteLink').hide('fast');
        $('#tbTargetDetails tr:last').after(row);
    }
请帮忙解决我的问题.非常感谢你的帮助.谢谢.
小智 8
您没有data-val在文本框中包含必要的属性,也没有包含用于显示验证消息的占位符元素,这些元素用于jquery.validate.unobtrusive.js进行客户端验证.此外,您当前的实现不允许用户通过包含索引器的隐藏输入来删除可以解决的最后一行的其他任何内容,这允许非连续索引器被发布并绑定到您的集合.
首先ClsTargetInfo,在TargetInfo属性中添加一个默认对象,然后在视图中生成html
<table id="table"> // add an id attribute
  <thead>.....</thead>
  <tbody is="tablebody"> // add an id attribute
    for(int i = 0; i < Model.TargetInfo.Count; i++)
    {
      <tr>
        <td>
          @Html.TextBoxFor(m => m.TargetInfo[i].TargetColor_U, new { id="", @class="form-control" }) // remove the unnecessary id attribute
          @Html.ValidationMessageFor(m => m.TargetInfo[i].TargetColor_U)
          // Add the following hidden input to only one column in the row
          <input type="hidden" name="TargetInfo.Index" value=@i />
        </td>
        <td>
          @Html.TextBoxFor(m => m.TargetInfo[i].TargetColor_V, new { id="", @class="form-control" }) // remove the unnecessary id attribute
          @Html.ValidationMessageFor(m => m.TargetInfo[i].TargetColor_V)
        </td>
        .... // other columns
      </tr>
    }
  </tbody>
</table>
然后检查它为生成的<tr>元素生成的html
<tr>
  <td>
    <input data-val="true" data-val-required="The TargetColor_U field is required" name="TargetInfo[0].TargetColor_U" type="text" value="">
    <span class="field-validation-valid errorText" data-valmsg-for="TargetInfo[i].TargetColor_U" data-valmsg-replace="true"></span>
    <input type="hidden" name="TargetInfo.Index" value="0" />
  </td>
  ....
</tr>
并将其复制到一个隐藏的元素内部,该元素放在表单标记之外,并用虚拟字符替换索引器的所有实例,因此name="TargetInfo[0].TargetColor_U"变为name="TargetInfo[#].TargetColor_U"),并且还替换value隐藏输入的属性,value="0"使其成为value="#"
<table id="newrow" style="display:none">
  .... // copy the tr element and its contents here
</table>
然后脚本看起来像
var form = $('form'); // or use the id if you have given the form an id
var newrow= $('#newrow');
var tablebody = $('#tablebody'); // modify to suit your id
$("#btnAddTarget").click(function() {
  var index = (new Date()).getTime(); // unique indexer
  var clone = newrow.clone(); // clone the new row
  clone.html($(clone).html().replace(/#/g, index)); // update the indexer of the clone
  var row = clone.find('tr');
  tablebody.append(row); // add the new row to the table
  // Reparse the validator
  form.data('validator', null);
  $.validator.unobtrusive.parse(form);
});
附注:
data-val首次呈现表单时解析属性来进行不显眼的验证.添加动态内容时,需要重新解析验证程序,如脚本的最后两行所示.<td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px">,您应该#table td { padding: 0; }在您的.css文件中使用[StringLength]属性),则需要更新html以适应.作为替代方案,您可以考虑使用
 BeginCollectionItem帮助程序,这意味着您有一个局部视图(表示一个表行).对于现有项,使用foreach带有@Html.Partial()和对于新行的
 循环,使用ajax调用返回局部视图的控制器方法,并更新DOM