ASP.NET TextBox值更新异常求助:客户端修改后验证失效
我使用了两个ASPX控件:
<asp:TextBox runat="server" ID="tbValue" MaxLength="18" Enabled="false" /> <asp:HiddenField runat="server" ID="hdtbValue" />
在客户端通过JavaScript函数为这两个控件设置相同值后,页面出现异常:浏览器控制台中执行document.getElementById('ctl00$ContentPlaceHolder1$tbValue').value得到结果是YYYYY,但该控件的innerHTML仍然是初始的预计算值XXXXX。
这直接导致我的ASP.NET验证器失效,因为它获取到的是旧值:
<asp:CustomValidator ID="cvtbValue" runat="server" Display="Dynamic" ValidationGroup="valNumericValue" ValidateEmptyText="true" ControlToValidate="tbValue" />
隐藏域HiddenField的值修改完全正常,但ASP:TextBox却出现上述异常,请问这是什么原因?
核心原因
当ASP.NET的TextBox控件设置Enabled="false"时,服务器端会将其渲染为带disabled属性的HTML input元素,而HTML规范对禁用元素有两个关键限制:
- 客户端修改禁用input的
value属性后,页面DOM的innerHTML不会同步更新——因为禁用元素的显示内容由初始渲染的HTML文本节点控制,而非动态修改的value属性。 - 禁用元素不会随表单提交到服务器,ASP.NET的验证器(包括CustomValidator)在服务器端验证时,只会读取控件的服务器端初始值(即
XXXXX),而非客户端修改后的YYYYY;同时客户端的ASP.NET验证脚本默认也会优先读取与innerHTML绑定的初始值,导致客户端验证也失效。
可行解决方案
你可以选择以下两种方案修复:
用
ReadOnly="true"替代Enabled="false"
将TextBox的属性改为ReadOnly="true",此时控件会渲染为带readonly属性的input元素:<asp:TextBox runat="server" ID="tbValue" MaxLength="18" ReadOnly="true" />只读元素的value属性修改会同步反映到页面显示,且表单提交时会将最新值发送到服务器,验证器能正确读取到更新后的值。
让验证器关联隐藏域而非禁用的TextBox
保留Enabled="false"的TextBox仅用于显示,将CustomValidator的ControlToValidate指向HiddenField,同时确保客户端更新值时两者同步:<asp:CustomValidator ID="cvtbValue" runat="server" Display="Dynamic" ValidationGroup="valNumericValue" ValidateEmptyText="true" ControlToValidate="hdtbValue" />注意:如果使用服务器端验证逻辑,需要在验证方法中读取HiddenField的值;如果有自定义客户端验证脚本,也要调整为验证隐藏域的值。
内容的提问来源于stack exchange,提问作者AbhishekS

