UPDATE: This control is now available from my CodePlex project @ http://www.codeplex.com/AspNetAjaxControls.

In this article I set out to breathe new life into the types of alerts, dialogs and prompts that are available to ASP.NET developers.  In ASP.NET web development we are typically limited to what the browser can support.  I am sure that most of us are very familiar with the JavaScript alert() and confirm() dialogs.  They are limited, not customizable, and do not support any rich HTML content.

The AJAX Control Toolkit introduced a few extender controls such as the “ModalDialog” Extender and the “ConfirmButton” extender.  These solved a few of our common issues, but they were still leaving me wanting for more.  I’ve taken what I’ve learned from using the above techniques and encapsulated them into one very extensible and easy to use prompt control for ASP.NET AJAX.

The prompt control builds upon the ASP.NET AJAX framework and derives from the “ScriptControl” server-side class and the “Sys.UI.Control” client-side class.  The prompt control also utilizes extender controls with client-side behaviors.

The Microsoft team did a great job developing the “UpdatePanel” and thought I would borrow a few ideas from this control.  Within the UpdatePanel a developer can setup triggers that would automatically cause an async-postbacks to occur.  With these triggers a ControlID and event were required.  I took a similar approach with the prompt control but instead of tying into server-side events I am tying into client-side events.

The prompt includes three default button options. Ok, OkCancel and YesNo.  If none of these default implementations suit your needs you can set the ButtonOptions property to “Custom” and define your own buttons within the <Buttons> section of the prompt control.

In Sample 1 I am demonstrating how a prompt can be triggered by capturing client-side events from web controls.

<ae:Prompt ID="prompt1" Title="Prompt Sample 1" Message="I am the Prompt sample." ButtonOptions="OK" runat="server">
    <Triggers>

        <ae:ControlPromptTrigger ControlID="submitButton" EventName="click" PreventDefault="true" />
       
<ae:ControlPromptTrigger ControlID="dropDown1" EventName="change" />
        <ae:ControlPromptTrigger ControlID="checkBox1" EventName="click" />

        <ae:ControlPromptTrigger ControlID="textBox1" EventName="focus" />

    </Triggers>

</ae:Prompt>


After defining the base prompt properties you can simply set up triggers that are linked to other controls on your ASP.NET page.  Within each trigger you must choose which client-side event to wire up to the prompt.  Note that these events are not the server-side events that the web controls expose, but the client-side events that their HTML rendering exposes.  Also note that we are not specifying the “on” plus event name.  One of the most common triggers would be the “click” event on a Button control.

The prompt control also contains a rich client-side api for manipulating the prompt client-side, as well as exposing some events that are useful when working with prompts.  In sample 2 I am demonstrating the “buttonSelect” event of the prompt control and reacting to the button that the user had selected after the prompt was shown.

<ae:Prompt ID="prompt1" Title="Prompt Sample 2" Message="I am prompt sample 2." ButtonOptions="Custom" OnCommand="prompt1_Command" runat="server">
    <ClientEvents
>
       
<ButtonSelect EventHandler="prompt1_ButtonSelect"
/>
   
</ClientEvents
>
   
<Triggers
>
       
<ae:ControlPromptTrigger ControlID="button1" EventName="click" PreventDefault="true"
/>
    </Triggers
>
    <Buttons
>
       
<ae:PromptButton ID="yesButton" CommandArgument="Yes" Text="Yes" AutoPostBack="true" runat="server"
/>
       
<ae:PromptButton ID="noButton" CommandArgument="No" Text="No" runat="server"
/>
       
<ae:PromptButton ID="cancelButton" CommandArgument="Cancel" Text="Cancel" runat="server"
/>
   
</Buttons
>
</
ae:Prompt>

All of the client-side events that the prompt controls expose are grouped up into a “ClientEvents” element within the prompt’s declaration. 

The “buttonSelect” event in this sample is wiring up the JavaScript function “prompt1_ButtonSelect”.  The buttonSelect event is of type buttonSelectEventArgs which contains a property called “button” that will then expose the button that the user selected within the prompt.

 <script type="text/javascript">
    function
prompt1_ButtonSelect(sender, args)
    {
        var
selectedButton = args.get_button();
        alert(
'You selected the "' + selectedButton.get_commandArgument() + '" button.'
);
    }
</script>

In some cases you may not want your prompt trigger to always fire.  To suppress the trigger you can specify a condition that has to be met for the trigger to actually fire.  In sample 3, we are setting up a ScriptCondition.  The script condition should link to a JavaScript function to evaluate your custom condition.

 <ae:Prompt ID="prompt1" Title="Prompt Sample 3" Message="I am prompt sample 3." ButtonOptions="Ok" runat="server">
    <Triggers
>
        <ae:ControlPromptTrigger ControlID="dropDown1" EventName="change" ScriptCondition="meetsCondition"
/>
    </Triggers
>
</
ae:Prompt>

This script condition passes an instance of CancelEventArgs to allow you to cancel the trigger from happening.

 <script type="text/javascript">
    function
meetsCondition(sender, args)
    {
       args.set_cancel($get(
'dropDown1'
).value == 2);
    }
</script>

In this sample, the trigger will be canceled if the user selected “Item 2” from the drop down list.  The prompt also includes a show and hide event that can be handled accordingly. See sample 5 for more details.

In addition to client-side events, the prompt also includes a rich client-side api to modify the display of the prompt including title, message, buttons, triggers, etc.

In sample 4, we can alter the title and message of the prompt by setting the title and message properties respectively.

 <script type="text/javascript">
    function
setPromptProperties()
    {
        var title = $get('promptTitle'
).value;
        var message = $get('promptMessage'
).value;
        var prompt = $find('prompt1'
);
        prompt.beginUpdate();
        prompt.set_title(title);
        prompt.set_message(message);
        prompt.endUpdate();
        prompt.show();
}
</script>

To ensure that the prompt only needs to render changes to the UI once, we have wrapped the property sets with a beginUpdate and endUpdate calls.  This will force all the DOM manipulation to happen together during the call to endUpdate().

One important feature of the prompt control is its ability to select which control receives the target of your postback.  When a prompt is configured to be triggered by an <asp:Button> control’s client-side click event you then have two options to choose from.  If your buttons are set to auto postback you might wonder whether the button’s click event or the prompts command event will be fired on the server.  The prompt contains a property called “PostBackTarget” which allows the developer to choose whether the prompt will be the target of the postback or if the control linked within a prompt trigger will be the target of the postback.  In sample 6 we can demonstrate this. 

<script type="text/javascript">
    function
prompt1_ButtonSelect(sender, args)
    {
        var prompt = $find('prompt1'
);
        var target = args.get_button().get_commandArgument() == 'prompt'

           ? AfterEdge.Web.UI.PostBackTarget.Prompt 
           : AfterEdge.Web.UI.PostBackTarget.Trigger;

        prompt.set_postBackTarget(target);
    }
</script>

This sample shows how when prompt buttons are set to AutoPostback = true,  the postBackTarget is set on the client depending on which button is selected.  After the postback has completed you can see which control actually received the target of the postback.  You generally don’t need to set the postback target on the client, I am merely demonstrating the flexibility of the control.  In my personal use of the control I typically declare the postback target in the prompt declaration and never change it.

An important thing to note is that when PreventDefault property of the prompt trigger is set to true, it cancels the immediate postback of the control to allow the prompt to display.  Upon selecting a button from the prompt, the postback will then complete.

The prompt control also has a server-side “Command” event which fires if the prompt receives the target of the postback.  Within the CommandEventArgs, the selected button’s command argument is passed to evaluate which button was selected on the client.

When developing an ASP.NET page, using server-side controls puts more overhead on your server than the traditional Html controls.  If server-side functionality is not required, I would recommend using standard Html controls.  The prompt also support creating triggers on Html controls by setting the ControlType property of the prompt trigger to “HtmlControl”.

<ae:Prompt ID="prompt1" Title="Prompt Sample 7" Message="I was triggered from a Html Control." ButtonOptions="Ok" runat="server">
    <Triggers
>
        <ae:ControlPromptTrigger ControlID="button1" ControlType="HtmlControl" EventName="click"
/>
    </Triggers
>
</
ae:Prompt>

The triggers will act just as they did on the web controls.  

I hope you enjoyed reading about this control and some of its common uses.  Please feel free to contact me if you have any questions or comments.  I have also included the binary and source for this control as a download to this post.

Happy programming.