如何在ASP .NET表单上使用jQuery UI对话框作为“提交前确认”对话框

6
我正在尝试利用jQuery UI(或任何其他对话框插件)来替换默认的确认对话框。在StackOverflow上有很多类似的问题和答案,例如:jquery dialog: confirm the click on a submit button
然而,在ASP .NET中我需要更多的东西。由于页面上只能有一个表单的限制,在使用ASP .NET 3.5的页面上,我可以有多个提交相同表单的按钮,并且基于提交的标头信息,Page 知道哪个控件(Button)触发了表单提交,并且可以在服务器上调用正确的方法(附加到Button的Click事件)。如果我使用其他StackOverflow答案中的解决方案,例如:
        buttons: {
            'Delete all items': function() {
                $(this).dialog('close');
                currentForm.submit();
            },
            'Cancel': function() {
                $(this).dialog('close');
            }
        }

在PostBack期间不会调用任何事件处理程序。如果我将它替换为:

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

这会导致无尽的模态对话框递归。如何在ASP .NET中解决它?

6个回答

3
作为一种选择,对于按钮控件可以使用SubmitBehavior="false",并将脚本放置在表单的结束标签之前:
<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>

如果您只想对特定按钮进行呼叫确认,可以使用下面的脚本(可以放置在页眉中)。该内容涉及IT技术。
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)" />

这将在任何后台运行,不仅仅是通过提交按钮进行表单提交。任何导致后台的操作都会被先停止并确认。 - dwerner

1

这是我的两分钱经验,适用于我的项目:

    // 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');
        });
    });

1
我最近使用了这个,虽然它只能与链接按钮一起使用。您可以对它们进行样式设置(毕竟它们只是锚点),使其看起来像HTML按钮。
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标记语言(如果您单击“确定”,将引发confirmMe_Click事件)

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

1
几个月前,我需要解决这个问题。我想在表单上有多个按钮,可能是在取消按钮上和模板重复器中包含的,并且所有按钮都能正确地请求适当的确认并根据用户操作提交表单或取消。下面的控件可以根据需要多次包含在表单中。它从System.Web.UI.WebControls.LinkButton继承,并使用控件的PostbackEventReference来知道哪个控件应该在确认后提交。如果您喜欢,该控件也可以轻松地从System.Web.UI.WebControls.Button继承。我选择使用链接按钮,因为它非常像按钮Web控件,但不会发出,而这种情况下不能使用jQuery UI样式化图标,除非使用控件适配器。
/// <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);
    }
}

0

我一段时间以前想出了这个解决方法,所以不确定它是否与最新的jquery-ui对话框插件保持同步,但你可以得到大致的想法。它利用了 eval 来执行由asp.net生成的javascript以提交放置在锚点href中的表单。你只需要给锚点一个confirm-required的css类即可。

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

0

我承认这有点冗长,但以下代码适用于我能想到的每种情况:

$(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
    });
});

使用ASP.Net 4.0框架和jQuery 1.8.2以及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>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接