Efter att ha läst MSDN-artikeln Asp.NET Validation in Depth blev jag tvungen att göra ett litet testcase för att se hur det fungerar om javascript är avstängt i webbläsaren. Jag gjorde följande HTML-sida:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Conditional Validation</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<div>
<asp:CheckBox ID="CheckBox1" runat="server" />
<asp:TextBox ID="TextBox1" runat="server" />
<asp:RequiredFieldValidator runat="server" ID="RequiredFieldValidator1"
ErrorMessage="RequiredFieldValidator"
ControlToValidate="TextBox1"
Enabled="false" />
<asp:Button ID="Button1" runat="server" Text="Button" />
<br /><br />
Output: <asp:Label ID="lblOutput" runat="server" Text="Label" />
</div>
</form>
<script type="text/javascript">
</script>
</body>
</html>
Här har vi alltså en checkbox, en textbox, en requiredFieldValidator och en knapp. Notera att validatorns Enabled-property är satt till false, detta eftersom jag vill validera textboxen endast om checkboxen är kryssad och det kommer den inte att vara när sidan laddas. Slutligen har vi en label som får sitt värde i sidans Page_Load-funktion:
protected void Page_Load(object sender, EventArgs e)
{
lblOutput.Text = string.Format("Postback = '{0}', Checkbox checked = '{1}', Textbox text = '{2}'",
IsPostBack.ToString(),
CheckBox1.Checked.ToString(),
TextBox1.Text);
}
För att valideringskontrollen ska aktiveras när kryssrutan är ikryssad lägger jag till följande javascript i sidan:
//<![CDATA[
function pageLoad()
{
$addHandler($get('<%=CheckBox1.ClientID %>'), 'click', CheckBox1_Click)
}
function CheckBox1_Click(e)
{
var validator = $get('<%=RequiredFieldValidator1.ClientID %>');
ValidatorEnable(validator, e.target.checked);
validator.style.visibility='hidden';
}
//]]>
För att den här javascript-koden ska fungera krävs att vi har en ScriptManager på sidan (rad 11 i html-koden), den ger mig tillgång till att använda Asp.NET AJAX-genvägar som $get och $addHandler. För att jag inte ska råka anropa dessa funktioner innan Asp.NET AJAX-scripten är ordentligt laddade använder jag mig av funktionen pageLoad. Den körs vid sidladdning, men först när alla AJAX-script är ordentligt laddade. I pageLoad lägger jag till en eventhandler för checkboxen så att funktionen CheckBox1_Click körs när man klickar i checkboxen. I CheckBox1_Click gör jag först en referens till min valideringskontroll och därefter anropar jag en funktion som heter ValidatorEnable. Det är en javascript-funktion som kommer att finnas tillgänglig i sidan om sidan innehåller en eller flera Asp.NET-valideringskontroller (i det här fallet en RequuriedFieldValidator). ValidatorEnable tar två argument, det första ska vara en referens till en valideringskontroll och det andra ska vara en boolean som avgör om valideringskontrollen blir enabled (true) eller disabled (false). För att koppla detta till om checkboxen är kryssad eller inte skickar jag helt enkelt in kryssrutans checked-egenskap som värde (e är referens till eventet, target är referens till det element som triggade eventet). Förutom att ValidatorEnable enablar eller disablar valideringskontrollen kör den också själva valideringen och visar felmeddelandet om valideringen inte går igenom. Detta blir lite konstigt om man först kryssar i checkboxen innan man hunnit skriva i något i textboxen. Detta åtgärdar jag genom att sist i funktionen dölja valideringskontrollen, den kommer att visas igen om jag klickar på knappen utan att fylla i textboxen.
Nu fungerar detta alldeles utmärkt så länge webbläsaren vi kollar med har javascript aktiverat. Men vad händer om javascript inte är aktiverat? Ja, då går det alldeles utmärkt att posta sidan även om checkboxen är kryssad samtidigt som textboxen är tom. Lösningen på problemet, som jag alltså uppmärksammades på här, är att i code-behind göra en override på Page-klassens Validate-funktion enligt följande:
public override void Validate()
{
RequiredFieldValidator1.Enabled = CheckBox1.Checked;
base.Validate();
}
Denna funktion kommer nu alltså att anropas innan den ordinarie valideringsfunktionen drar igång (via base.Validate()) och på så sätt kan vi se till att vi även på serversidan enablar och disablar olika valideringskontroller beroende på hur formuläret är ifyllt. Mer om kopplingarna mellan Asp.NET-valideringskontrollerna och Page-klassen kan du alltså läsa här.