In ASP.NET when using validation controls (i.e. RequiredFieldValidator
) the client sided framework will execute the JS function Page_ClientValidate
. This function will validate all controls on the page (of the given ValidationGroup
) and call the JS function ValidatorUpdateDisplay
with a parameter of the DOM element of the span
tag of the validator control.
ValidatorUpdateDisplay
toggles the visibility of the span
tag depending on the result of the validation.
In my web application I've overridden the ValidatorUpdateDisplay
JS function to provide more functionality on the validation scenario (i.e. red borders around the controls, showing popover on the first failed control and scrolling to it).
Now this works very well until my controls (incl. submit button) are shown the first time after a postback in an UpdatePanel.
<asp:ScriptManager runat="server" />
<asp:UpdatePanel ID="upTest" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button ID="bShow" runat="server" UseSubmitBehavior="false" Text="SHOW" OnClick="bShow_Click" />
<asp:Panel ID="pContent" runat="server" Visible="false">
<asp:TextBox ID="tbTest" runat="server" />
<asp:RequiredFieldValidator ID="rfvTest" runat="server" ControlToValidate="tbTest" Text="Not valid" />
<asp:Button ID="bTest" runat="server" UseSubmitBehavior="false" Text="TEST" />
</asp:Panel>
</ContentTemplate>
</asp:UpdatePanel>
<script type="text/javascript">
function ValidatorUpdateDisplay(val) {
debugger; // this will not be reached
}
</script>
protected void bShow_Click(object sender, EventArgs e)
{
this.pContent.Visible = true;
}
After initial load press bShow
to display pContent
.
Now, if you leave tbTest.Text
empty and press on bTest
it should enter the overridden ValidatorUpdateDisplay
function, however it enters the function of the framework and displays "Not valid" from rfvTest
.
If you change pContent.Visible
to true
and press bTest
after initial load the desired effect will happen: It will enter the custom ValidatorUpdateDisplay
function and not display "Not valid".
If you move the button bTest
out of the UpdatePanel
the problem persists.
How can I make it work inside an UpdatePanel
?
ASP.NET uses a lazy loading approach to insert the ValidatorUpdateDisplay
function when it needs it the first time, hence in my example it will load the function after the postback of the UpdatePanel
.
This will override my own implementation of the ValidatorUpdateDisplay
function, because it's inserting the function at the end of the page.
There is a dirty workaround, I just inserted an empty CustomValidator
on initial load that is always valid:
<asp:CustomValidator runat="server" />
I wish there was a cleaner solution.