为表格中的动态文本框设置类验证
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>
然后检查它为<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"
),并且还替换了 @隐藏输入的 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,例如,而不是 <td style="padding-left:0px;padding-top:0px;padding-bottom:0px;padding-right:0px">
,您应该在 .css
文件中使用 #table td padding: 0;
虽然纯客户端添加行可提供最佳性能,
它很难维护。如果您添加或更改任何验证
属性上的属性(例如,您以后可能会添加一个
[StringLength]
属性),您需要将 html 更新为
适合。作为替代方案,您可以考虑使用
BeginCollectionItem helper 这意味着你有一个部分
视图(表示表格行)。对于现有项目,您使用
foreach
与 @Html.Partial()
循环,对于新行,您使用 ajax
调用返回局部视图的控制器方法,以及
更新 DOM
【讨论】:
我已经尝试过了,但是发生了一些问题..在 div 中,我只是复制所有 tr 元素?它说元素<table>
(而不是 <div>
)
斯蒂芬..它的工作原理..只需改变 var row = clone.find('tr'); tablebody.append(row);但现在 以上是关于为表格中的动态文本框设置类验证的主要内容,如果未能解决你的问题,请参考以下文章