为表格中的动态文本框设置类验证

Posted

技术标签:

【中文标题】为表格中的动态文本框设置类验证【英文标题】:Set class validation for dynamic textbox in a table 【发布时间】:2015-07-02 11:18:18 【问题描述】:

我有一个有一行动态文本框的表格。示例如下:

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

我想为表格内的所有文本框添加验证类。所以当用户点击保存按钮时,它会检查所有的文本框。

我尝试使用这个 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"  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);
    

请帮助解决我的问题。真的很感谢你们的帮助。 谢谢。

【问题讨论】:

您是否将文本框绑定到模型?如果是这样,为什么不直接将 [Required] 属性添加到属性中,然后开箱即用地处理所有这些。以及如何动态添加元素? 如何添加新行 - 您是使用 BeginCollectionItem 帮助程序,还是手动添加 html 我已经为属性添加了所需的属性,但是当我点击保存按钮时仍然没有进行验证。 如何生成控件很重要 - 请参阅我的最后评论 您的实施存在多个问题。首先,因为您没有索引器的输入,如果您删除一行,绑定将失败。接下来,您无需添加必要的data-val 属性,因此无需验证。如果您确实生成了正确的 html,则所需要做的就是重新解析验证器。您还有很多不必要的 html(为什么要添加所有这些样式属性而不是仅应用 css?添加 id 属性有什么意义?)。我建议你考虑使用BeginCollectionItem() 助手。 【参考方案1】:
<script src="Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
    $(document).ready(function () 

        function DeleteRow(btn) 

            //alert("delete" + btn);
            var tr = btn.closest('tr');
            tr.remove();
        
        $(".btnsd").click(function () 
            // debugger;
            alert("hjkghk");
            divs = $('.val')
            for (ind in divs) 
                var div = divs[ind];
                if (div.value == "") 
                    div.focus();
                    return false;
                
            
            $('#Employertbl').append(
                                    '<tr>' +
                                        '<td> @Html.TextBox("item.employer_name", null, new  @class = "form-control val" )</td>' +
                                        '<td > <div style="float:left; padding-right:5px;">@Html.TextBox("item.duration_From", null, new  @id = "", @placeholder = "From Date", @class = "form-control input-date datepicker val", @readonly = true )</div> ' +
                                              '<div>@Html.TextBox("item.duration_to", null, new  @id = "", @class = "form-control input-date datepicker val", @placeholder = "To Date", @readonly = true )</div></td>' +
                                        '<td> @Html.TextBox("item.designation", null, new  @class = "form-control val" )</td>' +
                                        '<td> @Html.TextBox("item.worked_skill", null, new  @class = "form-control val" )</td>' +
                                        '<td> @Html.TextBox("item.proj_handled", null, new  @class = "form-control val" )</td>' +
                                        '<td>  @Html.CheckBox("item.current_employed",new@class = "current" )</td>' +
                                        '<td><input type="button" value="Remove" onclick="DeleteRow(this)" name="delete" class="btn blue pull-right" /> </td>' +
                                    '</tr>'
                                    );



        );
    );
</script>


<div class="table-responsive">
    <table id="Employertbl" class="table table-striped table-bordered table-hover dataTable no-footer">
        <tbody>
            <tr>
                <th>Employer Name</th>
                <th>Duration</th>
                <th>Designation</th>
                <th>Worked skill(s)</th>
                <th>Reason of change</th>
                <th>Currently Employed</th>
                <th>Action</th>
            </tr>

            <tr>
                <td>
                    <input class="form-control val" id="item_employer_name" name="item.employer_name" type="text" value="">
                </td>
                <td >
                    <div style="float:left; padding-right:5px;"><input class="form-control input-date datepicker val hasDatepicker" name="item.duration_From" placeholder="From Date"  type="text" value="" id="dp1459328857835"></div>
                    <div> <input class="form-control input-date datepicker val hasDatepicker" name="item.duration_to" placeholder="To Date"  type="text" value="" id="dp1459328857836"></div>

                </td>
                <td>
                    <input class="form-control val" id="item_designation" name="item.designation" type="text" value="">
                </td>
                <td>
                    <input class="form-control val" id="item_worked_skill" name="item.worked_skill" type="text" value="">
                </td>
                <td>
                    <input class="form-control val" id="item_proj_handled" name="item.proj_handled" type="text" value="">
                </td>
                <td>
                    <input class="current" id="item_current_employed" name="item.current_employed" type="checkbox" value="true"><input name="item.current_employed" type="hidden" value="false">
                </td>
                <td>
                    <input id="myButton" type="button" value="add"  name="delete" class="btnsd bcbn">
                </td>
            </tr>


            <tr><td> <input class="form-control val" id="item_employer_name" name="item.employer_name" type="text" value=""></td><td > <div style="float:left; padding-right:5px;"><input class="form-control input-date datepicker val hasDatepicker" name="item.duration_From" placeholder="From Date"  type="text" value="" id="dp1459328857837"></div> <div><input class="form-control input-date datepicker val hasDatepicker" name="item.duration_to" placeholder="To Date" type="text" value="" id="dp1459328857838"></div></td><td> <input class="form-control val" id="item_designation" name="item.designation" type="text" value=""></td><td> <input class="form-control val" id="item_worked_skill" name="item.worked_skill" type="text" value=""></td><td> <input class="form-control val" id="item_proj_handled" name="item.proj_handled" type="text" value=""></td><td>  <input class="current" id="item_current_employed" name="item.current_employed" type="checkbox" value="true"><input name="item.current_employed" type="hidden" value="false"></td><td><input type="button" id="myButton" value="add" name="delete" class="btnsd dfsd"> </td></tr>
            <tr><td> <input class="form-control val" id="item_employer_name" name="item.employer_name" type="text" value=""></td><td > <div style="float:left; padding-right:5px;"><input class="form-control input-date datepicker val hasDatepicker" name="item.duration_From" placeholder="From Date" type="text" value="" id="dp1459328857839"></div> <div><input class="form-control input-date datepicker val hasDatepicker" name="item.duration_to" placeholder="To Date"  type="text" value="" id="dp1459328857840"></div></td><td> <input class="form-control val" id="item_designation" name="item.designation" type="text" value=""></td><td> <input class="form-control val" id="item_worked_skill" name="item.worked_skill" type="text" value=""></td><td> <input class="form-control val" id="item_proj_handled" name="item.proj_handled" type="text" value=""></td><td>  <input class="current" id="item_current_employed" name="item.current_employed" type="checkbox" value="true"><input name="item.current_employed" type="hidden" value="false"></td><td><input type="button" id="myButton" value="add" name="delete" class="btnsd"> </td></tr>
        </tbody>
    </table>
</div>

【讨论】:

欢迎来到 Stack Overflow!尽管此答案可能是正确且有用的,但如果您 include some explanation along with it 解释它如何帮助解决问题,则最好。这在未来变得特别有用,如果有一个变化(可能不相关)导致它停止工作并且用户需要了解它曾经是如何工作的。谢谢!【参考方案2】:

您没有在文本框中包含必要的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>

然后检查它为&lt;tr&gt; 元素生成的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"),并且还替换了 @隐藏输入的 987654331@ 属性,所以 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 属性来工作 首次呈现表单时。添加动态内容时, 需要重新解析验证器,如最后两行所示 脚本。 为索引器添加隐藏输入允许您 删除集合中的任何行,因此删除“删除”按钮是 不再需要,并将为用户提供更好的体验。 与其使用内联样式,不如使用 css,例如,而不是 &lt;td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px"&gt;,您应该在 .css 文件中使用 #table td padding: 0; 虽然纯客户端添加行可提供最佳性能, 它很难维护。如果您添加或更改任何验证 属性上的属性(例如,您以后可能会添加一个 [StringLength] 属性),您需要将 html 更新为 适合。作为替代方案,您可以考虑使用 BeginCollectionItem helper 这意味着你有一个部分 视图(表示表格行)。对于现有项目,您使用 foreach@Html.Partial() 循环,对于新行,您使用 ajax 调用返回局部视图的控制器方法,以及 更新 DOM

【讨论】:

我已经尝试过了,但是发生了一些问题..在 div 中,我只是复制所有 tr 元素?它说元素 不能嵌套在元素 内 糟糕,抱歉,您需要将其设为 &lt;table&gt;(而不是 &lt;div&gt; 斯蒂芬..它的工作原理..只需改变 var row = clone.find('tr'); tablebody.append(row);但现在 出现在屏幕底部。我怎样才能让它消失? 使用 css - #newrow display: none; 将其设置为隐藏(或使用 &lt;table id="newrow" style="display:none;"&gt; 内联我已经更新了答案这在一定程度上对我有用,假设我的列是姓名和年龄,我添加 4 行,每个姓名将等于输入到第一行的内容,每个年龄都将等于放入第一行。

以上是关于为表格中的动态文本框设置类验证的主要内容,如果未能解决你的问题,请参考以下文章

VBA:如何验证子表单中的绑定文本框

Android界面中一个文本框,返回时保存数据,

在网格面板中动态更改 extjs 4 网格文本框背景颜色

如何在 MS Access VBA 上将文本框注释值输入设置为表格数据插入

验证检查带有单个提交按钮的动态文本框

如何让word文本框中的文字垂直上下居中