在表中设置动态文本框的类验证 [英] Set class validation for dynamic textbox in a table

查看:221
本文介绍了在表中设置动态文本框的类验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



p>

我通过点击[+]添加新目标在表格中添加一行。屏幕下方会显示:





我要添加验证类到表中的所有文本框。所以当用户点击保存按钮,它会检查所有的文本框。



我尝试使用这个jquery:

  $('#tbTargetDetails tr')。each(function(){
$(this).find('td input:text')。 (function(i,a){
//获取每个文本框并向其添加验证类
});
});

我使用MVC 5,jquery-1.10.2.js,jquery-1.10.2。 min.js,jquery.validate *&具有类 input.input-validation-error

的Site.css

在我的模型中:

  public class ClsTargetInfo 
{
public string ItemNumber_Target {get;组; }
[必需]
public string TargetColor_U {get;组; }
[必需]
public string TargetColor_V {get;组; }
[必需]
public string D90Target_U {get;组; }
[必需]
public string D90Target_V {get;组; }
[必需]
public string D10Target_U {get;组; }
[必需]
public string D10Target_V {get;组; }
[必需]
public string Thickness {get;组; }
[必需]
public string FilmWidth {get;组; }
[必需]
public string TargetDate {get;组; }
}



我在另一个模型中调用上面的模型:

  public class abc 
{
public IList< ClsTargetInfo> TargetInfo {get;组; }
}

下面是添加新行时的代码:

  $(#btnAddTarget)。on(click,function(event){
AddTargetItem(jQuery('#txtTargetColorU ').val(),jQuery('#txtD90TargetU')。val(),jQuery('#txtD10TargetU')。val(),
jQuery('#txtTargetColorV')。val #txtD90TargetV')。val(),jQuery('#txtD10TargetV')。val(),
jQuery('#txtThickness')。 ('#TargetDate')。val());
});

function AddTargetItem(TargetColor_U,D90Target_U,D10Target_U,TargetColor_V,D90Target_V,D10Target_V,Thickness,FilmWidth,TargetDate){
var rowCount = $('#tbTargetDetails tr')。
//为标题减去1行
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_Uname =TargetInfo ['+ rowCount +'] .TargetColor_Utype =textvalue ='+ 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_Vname =TargetInfo ['+ rowCount +'] .TargetColor_Vtype =textvalue ='+ 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_Uname =TargetInfo ['+ rowCount +'] .D90Target_Utype =textvalue ='+ 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_Vname =TargetInfo ['+ rowCount +'] .D90Target_Vstyle =text-align:center; type =textvalue ='+ 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_Uname =TargetInfo ['+ rowCount +'] .D10Target_Ustyle =text-align:center; type =textvalue ='+ 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_Vname =TargetInfo ['+ rowCount +'] .D10Target_Vstyle =text-align:center; type =textvalue ='+ 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 +'__Thicknessname =TargetInfo ['+ rowCount +'] .Thicknessstyle =text-align:center; type =textvalue ='+ Thickness +'/>< / td>';
row + ='< td style =padding-left:0px; padding-top:0px; padding-bottom:0px; padding-right:0px>< input class =form-control id =TargetInfo_'+ rowCount +'__FilmWidthname =TargetInfo ['+ rowCount +'] .FilmWidthstyle =text-align:center; type =textvalue ='+ FilmWidth +'/>< / td>';
row + ='< td style =padding-left:0px; padding-top:0px; padding-bottom:0px; padding-right:0px>< input class =form-control id =TargetInfo_'+ rowCount +'__TargetDatename =TargetInfo ['+ rowCount +'] .TargetDatestyle =text-align:center; type =textvalue ='+ TargetDate +'/>< / td>';
row + ='< td style =padding-left:0px; padding-top:0px; padding-bottom:0px; padding-right:0px; vertical-align:top;>< img id =imgRemoveTargetalt =Item Lookupsrc =/ Content / images / trashcan.pngstyle =cursor:pointer; width:32px; height:29px; class =deleteLink/>< / td>';
row + ='< / tr>';

//隐藏上一个删除按钮
$('#tbTargetDetails tr:last .deleteLink')hide('fast');

$('#tbTargetDetails tr:last')。after(row);
}

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

解决方案

您未包含必要的 data-val 属性到文本框,或者显示验证消息的占位符元素,它们由 jquery.validate.unobtrusive.js 用于执行客户端验证。此外,您当前的实现不允许用户删除任何其他可以解决的最后一行,包括索引器的隐藏输入,允许不连续的索引器发布并绑定到您的集合。



首先,在 TargetInfo 属性中添加一个默认 ClsTargetInfo 其在视图中的html

 < table id =table> // add a id attribute 
< thead> .....< / thead>
< tbody is =tablebody> //添加id属性
for(int i = 0; i {
< tr>
< td>
@ Html.TextBoxFor(m => m.TargetInfo [i] .TargetColor_U,new {id =,@ class =form-control})//删除不必要的id属性
@ html.ValidationMessageFor(m => m.TargetInfo [i] .TargetColor_U)
//将以下隐藏输入添加到行中的一列
< input type =hiddenname = TargetInfo.Indexvalue = @ i />
< / td>
< td>
@ Html.TextBoxFor(m => m.TargetInfo [i] .TargetColor_V,new {id =,@ class =form-control})//删除不必要的id属性
@ Html.ValidationMessageFor(m => m.TargetInfo [i] .TargetColor_V)
< / td>
.... //其他列
< / tr>
}
< / tbody>
< / table>

然后检查它为< tr> 元素应该看起来像

 < tr& 
< td>
< input data-val =truedata-val-required =TargetColor_U字段是必需的name =TargetInfo [0] .TargetColor_Utype =textvalue =
< span class =field-validation-valid errorTextdata-valmsg-for =TargetInfo [i] .TargetColor_Udata-valmsg-replace =true>< / span>
< input type =hiddenname =TargetInfo.Indexvalue =0/>
< / td>
....
< / tr>

并将其复制到位于表单标签的隐藏元素并用一个虚拟字符替换索引器的所有实例,因此 name =TargetInfo [0] .TargetColor_U变为 name =TargetInfo [#]。 TargetColor_U),并且替换隐藏输入的属性,因此 value =0变成 value =#

 < table id =newrowstyle =display:none> 
.... //复制tr元素及其内容
< / table>

然后脚本会像

  var form = $('form'); //或者使用id,如果你给出了一个id 
var newrow = $('#newrow');
var tablebody = $('#tablebody'); //修改以适应您的id
$(#btnAddTarget)。click(function(){
var index =(new Date())。getTime(); // unique indexer
var clone = newrow.clone(); //克隆新行
clone.html($(clone).html()。replace(/#/ g,index));克隆
var row = clone.find('tr');
tablebody.append(row); //将新行添加到表
// Reparse验证器
form.data('validator',null);
$ .validator.unobtrusive.parse(form);
});

附注:


  1. 不显眼的验证通过在首次呈现表单时解​​析 data-val 属性
    。当您添加动态内容时,如脚本的最后两行
    中所示,需要
    才能重新解析验证器。

  2. 添加隐藏索引器的输入允许您
    删除集合中的任何行,因此删除删除按钮是
    不再是必要的,并且将给用户更好的体验。

  3. 而是使用内联样式,而不是< td style =padding-left:0px; padding-top:0px; padding-bottom:0px; padding- right:0px> ,你应该使用 #table td {padding:0; }

  4. .css 文件中添加行纯粹的客户端提供了最佳性能,
    其难以维护。如果您在属性上添加或更改任何验证
    属性(例如,您可能稍后添加
    [StringLength] 属性),则需要将html更新为
    。或者,您可以考虑使用
    BeginCollectionItem 帮助程序,这意味着您有一个部分
    视图(表示表行)。对于现有项目,您使用
    foreach 循环 @ Html.Partial() ,您使用ajax
    调用返回部分视图的控制器方法,
    更新DOM


I have a table that have a row of dynamic textbox. Example below:

I add the row in the table by clicking the [+] Add New Target a it below screen will appear:

I want to add validation class to all text box inside the table. So when the user click the save button, it will check all the text box.

I try to use this jquery to this:

 $('#tbTargetDetails tr').each(function () {
            $(this).find('td input:text').each(function (i,a) {
                // get each of the textbox and add validation class to it
            });
        });

I'm using MVC 5, jquery-1.10.2.js, jquery-1.10.2.min.js, jquery.validate* & Site.css that have class input.input-validation-error

In my models:

 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; }
    }

I call above model inside another model:

public class abc
{
 public IList<ClsTargetInfo> TargetInfo { get; set; }
}

Below is the code when i adding the new row:

        $("#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);
    }

Please help to solve my issue. Really appreciate your guys help. Thank you.

解决方案

You are not including the necessary data-val attributes to the textboxes, or the placeholder elements for displaying the validation messages, which are used by jquery.validate.unobtrusive.js to do client side validation. In addition, your current implementation does not allow the user to remove anything other that the last row which can be solved by including a hidden input for the indexer which allows non consecutive indexers to be posted and bound to your collection.

First start by adding one default ClsTargetInfo object to your TargetInfo property and generate its html in the view

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

Then inspect the html it generates for the <tr> element which should look something like

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

and copy it inside a hidden element that is placed outside the form tags and replace all instance of the indexer with a dummy character so name="TargetInfo[0].TargetColor_U" becomes name="TargetInfo[#].TargetColor_U"), and also replace the value attribute of the hidden input so value="0" it becomes value="#"

<table id="newrow" style="display:none">
  .... // copy the tr element and its contents here
</table>

Then the script will look like

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

Side notes:

  1. Unobtrusive validation works by parsing the data-val attributes when the form is first rendered. When you add dynamic content, it is necessary to re-parse the validator as indicated in the last 2 lines of the script.
  2. The addition of the hidden input for the indexer allows you to delete any row in the collection, so removing the "delete" button is no longer necessary and will give the user a better experience.
  3. Rather that using inline styles, use css instead, for example, rather than <td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px">, you should use #table td { padding: 0; } in your .css file
  4. While adding the rows purely client side gives the best performance, its difficult to maintain. If you add or change any validation attributes on your properties (for example you might later add a [StringLength] attribute), you will need to update the html to suit. As an alternative, you can consider using the BeginCollectionItem helper which means you have one partial view (representing a table row). For existing items, you use a foreach loop with @Html.Partial() and for new rows, you use ajax to call a controller method that return a the partial view, and update the DOM

这篇关于在表中设置动态文本框的类验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆