6

I'm trying to take advantage of jQuery UI (or any other dialog plugin) in order to replace default Confirm dialog. There're plenty similar questions and answers on StackOverflow, for instance:

jquery dialog: confirm the click on a submit button

Yet, in ASP .NET I need something more.

Due to one form on the page constraint, on ASP .NET page (working with ASP .NET 3.5) I can have multiple buttons that submit the same form, and based on submitted header information Page knows which control (Button) triggered form submission, and correct method can be called on the server (method attached to Button's Click event).

If I use solution from other StackOverflow answers, for instance:

        buttons: {
            'Delete all items': function() {
                $(this).dialog('close');
                currentForm.submit();
            },
            'Cancel': function() {
                $(this).dialog('close');
            }
        }

no event handler will be called on PostBack. If I replace it with:

        buttons: {
            'Delete all items': function() {
                $(this).dialog('close');
                $buttonThatWasConfirmed.click();
            },
            'Cancel': function() {
                $(this).dialog('close');
            }
        }

it will result in endless modal dialog recursion. How to solve it in ASP .NET?

6 Answers 6

3

As an option: use SubmitBehavior="false" for Button controls and place script below before form's closing tag:

<script type="text/javascript">
    var originalDoPostBack = __doPostBack;
    __doPostBack = function (sender, args) {
        $("#dialog").dialog({
            modal: true,
            title: "Confirm action",
            buttons: {
                Yes: function () {
                    $(this).dialog("close");
                    originalDoPostBack(sender, args);
                },
                Cancel: function () {
                    $(this).dialog("close");
                }
            }
        });
    };
</script>

If you want call confirmation explicitely only for particular buttons, you may use script below (may be placed in header)

function confirmPostBack(sender, args) {
    $("#dialog").dialog({
        modal: true,
        title: "Confirm action",
        buttons: {
            Yes: function () {
                $(this).dialog("close");
                __doPostBack(sender.name, args || "");
            },
            Cancel: function () {
                $(this).dialog("close");
            }
        }
    });
    return false;
}

<asp:Button runat="server" Text="Click Me" OnClientClick="return confirmPostBack(this)" />
Sign up to request clarification or add additional context in comments.

1 Comment

This will run at any postback, though, not necessarily just on form submission by the submit button. Anything that causes postback would first be stopped and confirmed.
1

I had to solve this question a few months ago. I wanted to have multiple buttons on a form, maybe on a cancel button plus included in a templated repeater, and have all of them correctly ask for the appropriate confirmation and either submit the form or cancel based on the user action. The below control can be included on a form as many times as necessary. It inherits from System.Web.UI.WebControls.LinkButton and uses the control's PostbackEventReference to know which control to submit if confirmed. The control can easily inherit from System.Web.UI.WebControls.Button instead if you prefer. I chose to use a link button because it operates very much like the button web control but doesn't emit <input type=submit> which cannot be styled with icons using jQuery UI without using a control adapter.

/// <summary>
///     A <see cref="T:System.Web.UI.WebControls.LinkButton"/> with added jQuery UI functionality to provide a modal dialog box to cancel the form submit client side.
/// </summary>
/// <remarks>This class requires the inclusion of jQueryUI</remarks>
[DefaultProperty("Text")]
[ToolboxData("<{0}:jQueryUIConfirmedLinkButton runat=\"server\"></{0}:jQueryUIConfirmedLinkButton>")]
public class jQueryUIConfirmedLinkButton : LinkButton
{
    /// <summary>
    ///     Holds the postback event reference data so that the emitted client script can execute the postback if the user confirms the action.
    /// </summary>
    protected string eventReference = null;

    /// <summary>
    ///     Gets or sets the emitted dialog's ID attribute.
    /// </summary>
    /// <value>
    ///     The dialog's ID attribute.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("dialog")]
    [Localizable(true)]
    public string DialogCssID
    {
        get
        {
            String s = (String)ViewState["DialogCssID"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogCssID"] = value;
        }
    }

    internal protected string DialogID
    {
        get
        {
            return String.Format("{0}_{1}", this.ClientID, DialogCssID);
        }
    }

    /// <summary>
    ///     Gets or sets the content of the dialog. This can be plain text or HTML.
    /// </summary>
    /// <value>
    ///     The HTML or plain text content of the dialog.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("<p>Are you sure?</p>")]
    [Localizable(true)]
    public string DialogContent
    {
        get
        {
            String s = (String)ViewState["DialogContent"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogContent"] = value;
        }
    }

    /// <summary>
    ///     Gets or sets the title that will appear on the dialog.
    /// </summary>
    /// <value>
    /// The dialog's title.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("Confirm Action")]
    [Localizable(true)]
    public string DialogTitle
    {
        get
        {
            String s = (String)ViewState["DialogTitle"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogTitle"] = value;
        }
    }

    /// <summary>
    ///     Gets or sets the text that will appear on the confirmation button.
    /// </summary>
    /// <value>
    ///     The text that will appear on dialog's confirmation button.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("Yes")]
    [Localizable(true)]
    public string DialogConfirmButtonText
    {
        get
        {
            String s = (String)ViewState["DialogConfirmButtonText"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogConfirmButtonText"] = value;
        }
    }

    /// <summary>
    ///     Gets or sets the text that will appear on the dialog's rejection button.
    /// </summary>
    /// <value>
    ///     The text that appears on the dialog's rejection button.
    /// </value>
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("No")]
    [Localizable(true)]
    public string DialogRejectButtonText
    {
        get
        {
            String s = (String)ViewState["DialogRejectButtonText"];
            return ((s == null) ? String.Empty : s);
        }
        set
        {
            ViewState["DialogRejectButtonText"] = value;
        }
    }

    /// <summary>
    ///     Raises the <see cref="E:System.Web.UI.Control.Load" /> event. Emits the necessary client script for the control to function.
    /// </summary>
    /// <param name="e">The <see cref="T:System.EventArgs" /> object that contains the event data.</param>
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        this.eventReference = Page.ClientScript.GetPostBackEventReference(this, string.Empty);
        Page.ClientScript.RegisterStartupScript(this.GetType(), string.Format("{0}{1}", this.ClientID, "-DialogScript"), this.GetClientScript(), true);
        Page.ClientScript.RegisterClientScriptBlock(this.GetType(), string.Format("{0}{1}", this.ClientID, "-DialogShowScript"), string.Format("function {0}Confirm() {{$('#{0}').dialog('open');}}", this.DialogID), true);
        this.OnClientClick = String.Format("{0}Confirm();return false;", this.DialogID);
    }

    /// <summary>
    ///     Renders the contents of the control to the specified writer. Adds the dialog HTML container to the output stream.
    /// </summary>
    /// <param name="writer">A <see cref="T:System.Web.UI.HtmlTextWriter" /> object that represents the output stream to render HTML content on the client.</param>
    protected override void RenderContents(HtmlTextWriter writer)
    {
        base.RenderContents(writer);
        writer.AddAttribute("id", this.DialogID);
        writer.RenderBeginTag("div");
        writer.Write(this.DialogContent);
        writer.RenderEndTag();
    }

    public override void RenderEndTag(HtmlTextWriter writer)
    {
        base.RenderEndTag(writer);
    }

    /// <summary>
    ///     Gets the client script.
    /// </summary>
    /// <returns>A string that will be output to the client as script</returns>
    private string GetClientScript()
    {
        return string.Format(@"$(function () {{

                            $('#{0}').dialog({{
                                autoOpen: false,
                                modal: true,
                                resizable: false,
                                buttons: {{
                                    '{1}': function () {{
                                        $(this).dialog('close');
                                        eval({2});
                                    }},
                                    '{3}': function () {{
                                        $(this).dialog('close');
                                    }}
                                }},
                                title: '{4}'
                            }});
                          }});", this.DialogID, this.DialogConfirmButtonText, this.eventReference, this.DialogRejectButtonText, this.DialogTitle);
    }
}

Comments

1

I have used this lately, although it only works with a link button. You can style them (they're just anchors after all) to look like html buttons if you'd like.

js

$(function () {
    $("#confirmMe").click(function (e) {
        e.preventDefault();
        var $anchor = $(this);
        $("<div>Are you sure you want to do that?</div>").dialog({
            title: "Confirm",
            modal: true,
            buttons: {
                "Ok": function () {
                    window.location = $anchor.attr("href");
                },
                "Cancel": function () {
                    $(this).dialog("close");
                }
            }
        });
    });
});

.net markup (confirmMe_Click event will be raised if you click ok)

<asp:LinkButton Text="Open Me" runat="server" ID="confirmMe" 
    ClientIDMode="Static" onclick="confirmMe_Click" />

Comments

1

Those are my two cents, that worked for my project:

    // Initialices the behaviour when the page is ready
    $(function() {
        // Sets the function to be called when the confirmation button is pressed          
        $('.jqConfirmacionBorrar').click(function(e) {
            // Prevents the default behaviour of the button
            e.preventDefault();
            // Gets the name of the button that was clicked
            var ControlClickedName = $(this).attr('name');
            // Sets up the dialog to be called, with some custom parameters.
            // The important one is to do the postback call when the confirmation
            // button ('Aceptar' in spanish) is clicked.
            $("#DivConfirmacion").dialog({
                width: 650,
                modal: true,
                draggable: true,
                autoOpen: false,
                buttons: {
                    'Cancelar': function() {
                        $(this).dialog('close');
                        return false;
                    },
                    'Aceptar': function() {
                        $(this).dialog('close');
                        __doPostBack(ControlClickedName, '');
                        return true;
                    }
                }
            });
            // Opens the dialog to propt the user for confirmation
            $('#DivConfirmacion').dialog('open');
        });
    });

Comments

0

I came up with this work around a while back so not sure if its still up-to-date with the latest jquery-ui dialog plugin but you get the general idea. It makes (unfortunate) use of eval to execute the javascript asp.net generates to submit the form that's placed in the anchor's href. You just need to give the anchor the css class of confirm-required.

<div class="confirm-dialog ui-helper-hidden" title="Confirm">
    <span class="ui-icon ui-icon-alert"></span>
    <p>Are you sure?</p>
</div>

<script language="javascript" type="text/javascript">

$(function(){
    // call confirm dialog boxes from buttons that require it
    $(".confirm-required:isactive").click(function () {
        var callback = $(this).attr("href");
        return showConfirmDialog(callback);
    });
});

this.showConfirmDialog = function (callback) {
    $(".confirm-dialog").dialog("destroy");
    $(".confirm-dialog").dialog({
        autoOpen: true,
        modal: true,
        buttons: {
            "OK": function () {
                $(this).dialog("close");
                eval(callback);
            },
            "Cancel": function () {
                $(this).dialog("close");
            }
        }
    });

    return false;
};

</script>

Comments

0

I admit it's a little lengthy, but the following works for every case I can think of:

$(document).ready(function () {
    'use strict';
    var getParsedPostback = function getParsedPostback(self) {
        /*
         * self is a jQuery object. The purpose of this function is to extract the
         * __doPostBack function or the WebForm_DoPostBackWithOptions function as a
         * string, parse out the component arguments, and return it as a different
         * function to be used as a callback. If the postback function does not exist
         * as a string (in the case of a submit button, for instance) then the
         * returned callback should unbind any click handlers and then trigger the
         * element's click event.
         */
        var postback = self.data('postback'),
            trimLeft = /^\s+/,
            trimRight = /\s+$/,
            startingQuote = /^['"]/,
            endingQuote = /['"]$/,
            eventTarget,
            eventArgument,
            validation,
            validationGroup,
            actionUrl,
            trackFocus,
            clientSubmit;
        if (postback.substring(postback.length - 1, postback.length) === ';') {
            //remove the trailing ";"
            postback = postback.substring(0, postback.length - 1);
        }
        if (postback.indexOf('javascript:') === 0) {
            //remove the "javascript:"
            postback = postback.substring(('javascript:').length, postback.length - 1);
        }
        //in case postback is in the form __doPostBack(&#39;XXXXXX&#39;,&#39;XXXXXX&#39;)
        postback = decodeURIComponent(postback);
        //parse by case
        if (postback.indexOf('__doPostBack(') === 0) {
            //postback should now be __doPostBack('XXXXXX','XXXXXX')
            postback = postback.substring(('__doPostBack(').length, postback.length - 2);
            postback = postback.split(',');
            eventTarget = encodeURIComponent(postback[0].replace(startingQuote, '').replace(endingQuote, ''));
            eventArgument = encodeURIComponent(postback[1].replace(startingQuote, '').replace(endingQuote, ''));
            postback = function () {
                __doPostBack(eventTarget, eventArgument);
            };
        } else if (postback.indexOf('WebForm_DoPostBackWithOptions(') === 0) {
            //postback should now be WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions('XXXXXX', 'XXXXXX', 'XXXXXX', 'XXXXXX', 'XXXXXX'))
            postback = postback.substring(('WebForm_DoPostBackWithOptions(').length, postback.length - 2);
            postback = postback.split(',');
            eventTarget = encodeURIComponent(postback[0].replace(startingQuote, '').replace(endingQuote, ''));
            eventArgument = encodeURIComponent(postback[1].replace(startingQuote, '').replace(endingQuote, ''));
            validation = !!postback[2].replace(startingQuote, '').replace(endingQuote, '');     //use !! to convert string to boolean
            validationGroup = encodeURIComponent(postback[3].replace(startingQuote, '').replace(endingQuote, ''));
            actionUrl = encodeURIComponent(postback[4].replace(startingQuote, '').replace(endingQuote, ''));
            trackFocus = !!postback[5].replace(startingQuote, '').replace(endingQuote, '');     //use !! to convert string to boolean
            clientSubmit = !!postback[6].replace(startingQuote, '').replace(endingQuote, ''); //use !! to convert string to boolean
            postback = function () {
                __doPostBack(new WebForm_PostBackOptions(eventTarget, eventArgument, validation, validationGroup, actionUrl, trackFocus, clientSubmit));
            };
        } else if (postback === 'submit') {
            //no apparent postback handler, must be a submit or an image
            postback = function () {
                //unbind the assigned click handler
                self.unbind('click');
                //trigger the click event
                self.click();
            };
        }
        return postback;
    };
    var clickHandler = function clickHandler(e) {
        var postback = getParsedPostback($(this)); //get the postback as a callback
        $('div#dialog').dialog('option', {
            "buttons": {
                "Delete all items": function () {
                    $(this).dialog('close');
                    postback(); //call the postback
                },
                "Cancel": function () {
                    $(this).dialog('close');
                }
            }
        }).dialog('open');
        e.preventDefault();
        return false;
    };
    var storePostbacks = function storePostbacks() {
        /*
         * The purpose of this function is to remove any existing __doPostBack functions
         * or WebForm_DoPostBackWithOptions functions and store them in the "data" for
         * the element. The "getParsedPostback" function above wil make extensive use of
         * the element's "data" to parse a usable callback for postback.
         */
        $('input[type="submit"], input[type="button"], input[type="image"], a[href*="__doPostBack"]').each(function (i, elem) {
            var self = $(elem),
            postback = '';
            if (typeof self.attr('onclick') !== 'undefined') {
                //store the postback in data and remove from the element.
                postback = self.attr('onclick');
                self.removeAttr('onclick').data('postback', postback);
            } else if (typeof self.attr('href') !== 'undefined') {
                //store the postback in data and remove from the element.
                postback = self.attr('href');
                self.attr('href', '#').data('postback', postback);
            } else if (self.attr('type') === 'submit' || self.attr('type') === 'image') {
                //flag as a submit.
                self.data('postback', 'submit');
            }
        });
    };
    storePostbacks();
    $('input#<%#aspButton1.ClientID %>').click(clickHandler);
    $('input#<%#aspButton2.ClientID %>').click(clickHandler);
    $('input#<%#aspImageButton.ClientID %>').click(clickHandler);
    $('a#<%#aspLinkButton.ClientID %>').click(clickHandler);
    $('div#dialog').dialog({
        "autoOpen": false
    });
});

Tested on the following markup using the ASP.Net 4.0 Framework with jQuery 1.8.2 and jQueryUI 1.9.0:

<body>
    <form id="form1" runat="server">
    <div>
        <div id="dialog">
            <p>Test of dialog.</p>
        </div>
        <div id="controls">
            <asp:Button ID="aspButton1" runat="server" Text="aspButton1" />
            <asp:LinkButton ID="aspLinkButton" runat="server">LinkButton</asp:LinkButton>
            <asp:ImageButton ID="aspImageButton" runat="server" />
            <asp:Button ID="aspButton2" runat="server" Text="aspButton2" />
        </div>
    </div>
    </form>
</body>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.