クライアント検証が成功した時だけAnimationExtenderを動かすには?

久しぶりのASP.NETネタ。

例えば以下のようなフォームがあるとする。

単純なフォームだけど、この「答える」ボタンをクリックした時に二度押しを防止するために無効化するということをよくやると思う。

ASP.NETの場合、AJAXControlToolkitに含まれている「AnimationExtender」を使えば簡単にこれを実現できる。

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>

<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajax" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <asp:ScriptManager ID="ScriptManager1" runat="server">
        </asp:ScriptManager>

        <div>
            <asp:Label runat="server" Text="あなたのお名前なんてーの?" Font-Size="Small" />
            <br />
            <asp:TextBox ID="nameText" runat="server" />
            <br />
            <asp:RequiredFieldValidator ID="nameText_Validator" runat="server" ErrorMessage="※名前を入力して下さい。"
                ControlToValidate="nameText" Display="Dynamic" SetFocusOnError="True" Font-Size="Small" />

            <div style="margin-top: 5px;">
                <asp:Button ID="Button1" runat="server" Text="答える" OnClick="Button1_Click" />
                <ajax:AnimationExtender ID="Button1_AnimationExtender" runat="server" Enabled="True"
                    TargetControlID="Button1">
                    <Animations>
                        <OnClick>
                            <EnableAction Enabled="false" />
                        </OnClick>
                    </Animations>
                </ajax:AnimationExtender>
            </div>

        </div>

    </form>
</body>
</html>

ボタンに対してAnimationExtenderを設定して、「Animations」タグの中でアニメーションを設定している。

<Animations>
    <OnClick>
        <EnableAction Enabled="false" />
    </OnClick>
</Animations>

ここではボタンがクリックされた時(OnClick)に「EnableAction」を使ってボタンの有効状態を設定している。

これで「答える」ボタンをクリックした時にボタンが無効化されるというわけだ。

一見これで問題が無いように見えるけど、今回の場合はテキストボックスに対して「RequiredFieldValidator」を使って、入力値の必須チェックを行っている。でも、AnimationExtenderは検証が成功したかどうかに関わらずアニメーションを実行してしまうので、この結果は残念なものになってしまう(ボタンは無効化されるけど、検証が通っていないのでSubmitがされない)。

で、今回の話はこれをどうやって回避するかというはなし。

これを解決するのは案外簡単で、AnimationExtenderのアニメーションにはJavaScript関数を呼び出して、その結果に応じてアニメーションを実行するかどうかを判断してくれる「Condition」というのが用意されている。

この「Condition」タグの「ConditionScript」という属性にクライアント検証が成功したかどうかを調べるJavaScript関数を書いてやればいい。クライアント検証が成功したかどうかを調べるには「Page_ClientValidate」関数を呼び出す*1

<Animations>
    <OnClick>
        <Condition ConditionScript="Page_ClientValidate();" Duration="0">
            <EnableAction Enabled="false" />
        </Condition>
    </OnClick>
</Animations>

検証グループを設定している場合は「Page_ClientValidate」関数の引数に検証グループ名を渡してやればいい。

ちょっと余分な処理が入るけど、そんなに気にするレベルではないのでよしとする。

*1:実際にはこの関数で検証が走るので実質二回検証することになるけど、まぁいいだろう