Thursday, January 17, 2008

Using AjaxControlToolkit ModalPopup Control to Show Confirmation Dialog Instead of Javascript "confirm" Popup Box

In previous blog post we created simple popup box behaving like javascript "alert" function.

This time I want to create universal confirm dialog. I suppose it will work like this:

1) Dialog should be shown from client script. We should be able to call it with javascript function.

2) Javascript function will take three parameters: button object that invoked the function, title - text that will appear as title of confirmation dialog, and html - text tat will appear inside popup dialog - html parameter will be the question or warning that the user will see inside confirmation box.

3) Confirmation dialog will have two buttons - Yes and No (OK/Cancel). Clicking on "No" will do nothing - confirmation dialog will just hide. Clicking "Yes" will post back the button that invoked confirmation dialog to the server, and the server will process event for that button.

The completed demo looks like:

image

You can see it online or download source code.

The trick with posting back a corresponding button works simple. When invoking javascript function responsible for showing dialog, we pass instance of a button object that invoked the function. This way we know the button.name property, and later we can post back the value to the server if user clicked "Yes".

To accomplish this task I created the following files:

Script.js:

/// --------------------------------------------------
/// mainScreen object
/// --------------------------------------------------
var mainScreen =
{
    mainModalExtender : null,           // modalExtender object on main page
    mainModalTitleSpan : null,          // title span object
    mainModalContentsDiv : null,        // div inside modal dialog
    pageTheme : "Default"
}

mainScreen.Init = function() {
    /// <summary>
    /// Initializes mainScreen variables
    /// </summary>
    this.mainModalExtender = $find('mbMain');
    this.mainModalTitleSpan = $get("spanTitle");
    this.mainModalContentsDiv = $get("mainModalContents");
};
mainScreen.ShowConfirm = function(_button,_title, _html) {
    /// <summary>
    /// Shows modal dialog with contents equal to _html
    /// </summary>
    /// <param name="_button">Button object</param>
    /// <param name="_title">Title of modal popup</param>
    /// <param name="_html">HTML that should be shown inside popup</param>
    this.currentButtonUID = _button.name
    this.mainModalTitleSpan.innerHTML = _title;
    this.mainModalContentsDiv.innerHTML = _html;
    this.mainModalExtender.show();
};
mainScreen.CancelConfirm = function() {
    /// <summary>
    /// Hides modal dialog 
    /// </summary>
    this.mainModalExtender.hide();
    this.currentButtonUID = null;
};
mainScreen.SubmitConfirm = function() {
    /// <summary>
    /// Hides modal dialog 
    /// </summary>
    if(this.currentButtonUID) {
        __doPostBack(this.currentButtonUID, "");
    }
    this.mainModalExtender.hide();
    this.currentButtonUID = null;
};


/// --------------------------------------------------
/// Page events processing
/// --------------------------------------------------

Sys.Application.add_load(
    applicationLoadHandler
    );
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(
    endRequestHandler
    );
Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(
    beginRequestHandler
    );

function applicationLoadHandler() {
    /// <summary>
    /// Raised after all scripts have been loaded and 
    /// the objects in the application have been created 
    /// and initialized.
    /// </summary>
    mainScreen.Init()
}

function endRequestHandler() {
    /// <summary>
    /// Raised before processing of an asynchronous 
    /// postback starts and the postback request is 
    /// sent to the server.
    /// </summary>
    
    // TODO: Add your custom processing for event
}

function beginRequestHandler() {
    /// <summary>
    /// Raised after an asynchronous postback is 
    /// finished and control has been returned 
    /// to the browser.
    /// </summary>

    $get("resultDiv").innerHTML = 
        "<img src='App_Themes/"+
        mainScreen.pageTheme+
        "/Img/activity_small.gif'/>";
}

Default.aspx:

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

<%@ 
    Register 
    assembly="AjaxControlToolkit" 
    namespace="AjaxControlToolkit" 
    tagprefix="AjaxToolkit" %>

<!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>
        Using AjaxControlToolkit ModalPopup Control 
        to Show Confirmation Dialog Instead 
        of Javascript "confirm" Popup Box
    </title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager 
        EnablePageMethods="true" 
        ID="MainSM" 
        runat="server" 
        ScriptMode="Release"
        LoadScriptsBeforeUI="true">
        <Scripts>
            <asp:ScriptReference 
                Path="~/Scripts/Main.js" />
        </Scripts>
    </asp:ScriptManager>
    <div>
        This sample shows confirm dialog 
        when you click on any button on the page.
        If you confirm the query, 
        original button you clicked 
        will be posted back to the server
        using __doPostBack('button.UniqueID','') method.
        So you can process event as normally in the code behind code.
        <br />
        <br />
        <asp:UpdatePanel 
            runat="server" 
            ID="up"
            UpdateMode="Conditional"
            >
            <ContentTemplate>
                <div>
                    <asp:Button
                        runat="server"
                        ID="btn1"
                        Text="btn1" 
                        onclick="btn1_Click"
                        OnClientClick="
                        mainScreen.ShowConfirm(
                            this,
                            'Please confirm',
                            'Are you sure to submit &lt;b&gt;btn1&lt;/b&gt;?'
                        );
                        return false;"
                        />
                    &nbsp;
                    <asp:Button
                        runat="server"
                        ID="btn2"
                        Text="btn2" 
                        onclick="btn2_Click"
                        OnClientClick="
                        mainScreen.ShowConfirm(
                            this,
                            'Please confirm',
                            'Are you sure to submit &lt;b&gt;btn2&lt;/b&gt;?'
                        );
                        return false;"
                        />
                    &nbsp;
                    <asp:Button
                        runat="server"
                        ID="btn3"
                        Text="btn3" 
                        onclick="btn3_Click"
                        OnClientClick="
                        mainScreen.ShowConfirm(
                            this,
                            'Please confirm',
                            'Are you sure to submit &lt;b&gt;btn3&lt;/b&gt;?'
                        );
                        return false;"
                        />
                    &nbsp;
                    <asp:Button
                        runat="server"
                        ID="btn4"
                        Text="btn4" 
                        onclick="btn4_Click"
                        OnClientClick="
                        mainScreen.ShowConfirm(
                            this,
                            'Please confirm',
                            'Are you sure to submit &lt;b&gt;btn4&lt;/b&gt;?'
                        );
                        return false;"
                        />
                    &nbsp;
                    <!-- 
                        We set UseSubmitBehavior="false"
                        to have __doPostBack function present
                        in the scope of the page
                     -->
                    <asp:Button
                        UseSubmitBehavior="false"
                        runat="server"
                        ID="btn5"
                        Text="btn5" 
                        onclick="btn5_Click"
                        OnClientClick="
                        mainScreen.ShowConfirm(
                            this,
                            'Please confirm',
                            'Are you sure to submit &lt;b&gt;btn5&lt;/b&gt;?'
                        );
                        return false;"
                        />
                    <br /><br />
                </div>
                <div 
                    style="border: dashed 1px black; 
                        font-weight:bold;
                        height:20px;" 
                    id="resultDiv"
                    runat="server"
                    >
                    &nbsp;
                </div>
            </ContentTemplate>
        </asp:UpdatePanel>
        <br /><br />
        <br />
        <br />
        <asp:Panel 
            ID="MPanel" 
            runat="server" 
            Style="display: none">
            <table 
                class="mainModalTable" 
                cellpadding="0" 
                cellspacing="0">
                <tr>
                    <td 
                        class="mainModaTableTD">
                        <table 
                            class="mainModalInnerTable" 
                            cellspacing="0" 
                            cellpadding="0">
                            <tr>
                                <td 
                                    class="mainModalInnerTableTD">
                                    <table 
                                        border="0" 
                                        width="100%" 
                                        cellspacing="0" 
                                        cellpadding="4">
                                        <tr>
                                            <td 
                                                class="mainModalDraggablePanelTD">
                                                <asp:Panel 
                                                    CssClass="mainModalDraggablePanel" 
                                                    ID="MPD" runat="server">
                                                    <span 
                                                        class="mainModalTitle" 
                                                        id="spanTitle" 
                                                        Text="">
                                                    </span>
                                                </asp:Panel>
                                            </td>
                                            <td 
                                                align="right" 
                                                class="mainModalDraggablePanelCloseTD">
                                                    <asp:ImageButton 
                                                        SkinID="CloseModal" 
                                                        runat="server" 
                                                        ID="clB" />
                                            </td>
                                        </tr>
                                        <tr>
                                            <td 
                                            style="text-align:center"
                                                class="mainModalContentsTD" 
                                                colspan="2">
                                                <div 
                                                    id="mainModalContents">
                                                </div>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td 
                                                class="mainModalContentsTD" 
                                                align="center"
                                                colspan="2">
                                                <input
                                                    type="button"
                                                    value="Yes"
                                                    onclick="mainScreen.SubmitConfirm();"
                                                    class="btn btnYes"
                                                    />
                                                &nbsp;
                                                <input
                                                    type="button"
                                                    value="No"
                                                    onclick="mainScreen.CancelConfirm();"
                                                    class="btn btnCancel"
                                                    />
                                            </td>
                                        </tr>
                                    </table>
                                    </td>
                            </tr>
                        </table>
                    </td>
                </tr>
            </table>
        </asp:Panel>
        <AjaxToolkit:ModalPopupExtender 
            ID="mpeModal" 
            runat="server" 
            PopupControlID="MPanel"
            TargetControlID="btnHid"
            BehaviorID="mbMain"
            BackgroundCssClass="modalBackground" 
            CancelControlID="clB"
            OnCancelScript="mainScreen.CancelConfirm();" />
        <asp:Button 
            runat="server" 
            ID="btnHid" 
            style="display:none;" />    
    </div>
    </form>
</body>
</html>

and CSS files.

Hope this helps.

8 comments:

Anonymous said...

Thank you! This is a really good article. I was trying to figure out the modal popup extender...thanks to your article, my code is now up & running. The only thing that I cannot figure out is why I can't use a LinkButton instead of a Button control to start the postback process. I did try updating the ShowConfirm function in "main.js" to use the proper control ID ("this.currentButtonUID = _button.id" instead of "this.currentButtonUID = _button.name"). No luck, tho.

Anyhow, thanks again for the helpful post.
- GreggTB

Kirill Chilingarashvili said...

Hello GreggTB,

Sorry to being late to answer you, I was a little busy these days and did not notice the comment notification.

ABout the LinkButtons .. -
I think this is because I use __doPostBack function in the conformation chunk of code.
But this is not only the function that is used to postback the data to the server.
There is also __doPostBackWithOptions function, so if you need to use some another control just see the source of the generated web page and find your link button there, It will have onclick attribute. You can see what function is uses to post the data to the server and use that in the modalpopup instead of __doPostBack.

Hope this helps.

Anonymous said...

Okay, I'll try that. Thanks again for the excellent article. You've been a huge help!
- GreggTB

Anonymous said...

Excellent article -- thank you.

One thing I am having trouble with is that I keep getting

"Sys.WebForms.PageRequestManager.getInstance() is null or not an object."

when the main page loads up. Popup still functions as expected. Any help would be appreciated.
--Chad

Anonymous said...

Please disregard earlier question. I found the error and it was mine. Great article.
--Chad

Anonymous said...

this doesn't exactly behave like a javascript confirm does it? This solution does not 'block thread' while the user selects an option nor does it return a true/false.
Is there anyone who can demonstrate how to use the ModalPopupExtender with the same sort of call semantics as the javascript confirm?

Anonymous said...

what is the function of
asp:Button
runat="server"
ID="btnHid"
style="display:none;"
??

Anonymous said...

Очень полезно