Using jQuery Modal Dialog Confirmation with an ASP.NET Server Control

So the other day, I wanted to build a confirmation dialog using jQuery with an existing Asp.Net web forms Button control.  I wanted this dialog to be modal; and upon confirmation, I wanted it to postback using the Button's server-side click event.  After toying with the jQuery dialog, I realized that its dialog doesn’t suspend the process while waiting for user input. So it also causes problems with confirmation since clicking the original button will always postback. So with a few tweaks, you can prevent the postback and emulate the click event pretty easily.

Setup the Dialog and Postback Script

In my application, we may click the button multiple times. So you’ll need to initialize it on load and actually open it later. As you can see below, we're making our dialog modal and setting its autoOpen to false to prevent it from opening during initialization.  The dialog contains two buttons, and in this initialization, we can define their handler code. The confirmation button “Yes, I Understand and Agree” runs a chunk of code emulates the server control Click event on Button1. Notice I used the inline server-side script to gain access to the Page.ClientScript object, which contains a nice handful of helper functions for javascript.

$().ready(function() {  
    $("#ConfirmPanel").dialog(
    { autoOpen: false,
        modal: true,
        bgiframe: true,
        width: 400,
        height: 300,
        buttons: {
            'Youbetcha': function() {
                <%=this.Page.ClientScript.GetPostBackEventReference(new PostBackOptions(this.Button1))%>;
            },
            'No Thanks': function() {
                $(this).dialog('close');
            }
        }
    })
});

Open the Dialog with OnClientClick

Next we’ll open the dialog each time our original server control button is clicked. You use the OnClientClick property to do this.

$("#ConfirmPanel").dialog('open'); return false;

We always return false here. Since the dialog doesn’t suspend the process, it will always finish and immediately postback. So by returning false, we’re preventing the button from posting back and allowing the jquery dialog to appear.

Here’s the full Asp.Net markup:

<asp:Label ID="lblClicked" runat="server" />  
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Test" OnClientClick="javascript: $('#ConfirmPanel').dialog('open'); return false;"/>
<div id="ConfirmPanel" style="width: 400px; height: 200px;">
    <h2>Terms and Conditions</h2>
    <p>By accepting, you agree to the following:
        <ul>
            <li>Are you really, really sure???? </li>
        </ul>
    </p>
</div>

The Result

image

Clicking Youbetcha fires the Click event for our Button1.

image

Updated: 2/16/2010

To answer Matt’s question, I setup a simple web forms page with a data grid and a button within its rows. All the buttons are wired to one event handler and their command argument property is used to provide identifying data to the event handler.  Having said that, here’s the same solution using dynamic confirmation dialog. If you click OK, it will postback using the original button’s information which is displayed on postback.  Noticed I placed a ClientScript.GetPostBackEventReference(uxGrid, string.Empty) within the PageLoad event. Every time the page loads, postback or not, I want it to do this so it will render the __doPostBack client-side function. Without that, it will only work the first time. Subsequent clicks after the first postback will break.

So essentially the solution is to use _doPostBack(clientsideinputnameattribute, '').  Using the javascript function below we rebuild the buttons for the dialog each time and rewire it to the appropriate location.  So for this, if you didn't want to use a grid, you could still use it the same way via OnClientClick with "this.name" and pass that to __doPostBack.

Here’s the markup source.  You can also download the full source code here.

Thanks Matt.

<%@ Page Language="C#" AutoEventWireup="true"  %>  
<%@ Import Namespace="System.Collections.Generic" %>

<!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>

    <script type="text/C#" runat="server">
        protected void Page_Load(object sender, EventArgs e)
        {
            ClientScript.GetPostBackEventReference(uxGrid, string.Empty);

            if (!Page.IsPostBack)
            {
                List<int> test = new List<int>();
                test.Add(2);
                test.Add(3);
                test.Add(32);
                test.Add(223);
                test.Add(5);
                test.Add(8);
                uxGrid.DataSource = test;
                uxGrid.DataBind();

            }
        }
        protected void uxRowAction_Click(object sender, EventArgs e)
        {
            Button b = sender as Button;
            if (b != null)
            {
                uxTest.Text = "clicked " + b.CommandArgument;
            }
        }

    </script>

    <link href="smoothness/jquery-ui-1.7.2.custom.css" rel="stylesheet" type="text/css" />
    <script src="jquery-1.3.2.min.js" type="text/javascript"></script>
    <script src="jquery-ui-1.7.2.custom.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $().ready(function() {
            $('#dialogContent').dialog({
                autoOpen: false,
                modal: true,
                bgiframe: true,
                title: "MySql Membership Config Tool",
                width: 800,
                height: 600
            });
        });

        function rowAction(uniqueID) {

            $('#dialogContent').dialog('option', 'buttons',
                {
                    "OK": function() { __doPostBack(uniqueID, ''); $(this).dialog("close"); },
                    "Cancel": function() { $(this).dialog("close"); }
                });

                $('#dialogContent').dialog('open');

            return false;
        }

    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div id="dialogContent">
        <h3>confirm</h3>
        <p>Click ok to accept</p>
    </div>
    <asp:Literal ID="uxTest" runat="server" />
    <div>
        <asp:DataGrid ID="uxGrid" runat="server" AutoGenerateColumns="false">
            <Columns>
                <asp:TemplateColumn>
                    <ItemTemplate>
                        <asp:Button ID="uxRowAction" runat="server" CommandArgument='<%#Container.DataItem.ToString() %>' Text="Row Action" OnClick="uxRowAction_Click" OnClientClick="javascript:return rowAction(this.name);" />
                    </ItemTemplate>
                </asp:TemplateColumn>
            </Columns>
        </asp:DataGrid>
    </div>
    </form>
</body>
</html>