2012-10-19 28 views
6

Tôi đang cố gắng tận dụng lợi thế của jQuery UI (hoặc bất kỳ plugin thoại nào khác) để thay thế hộp thoại Xác nhận mặc định. Như vậy là rất nhiều câu hỏi tương tự và câu trả lời trên StackOverflow, ví dụ:Cách sử dụng Hộp thoại Giao diện người dùng jQuery như hộp thoại "xác nhận trước khi gửi" trên mẫu ASP .NET

jquery dialog: confirm the click on a submit button

Tuy nhiên, trong ASP NET Tôi cần một cái gì đó nhiều hơn nữa.

Do một mẫu trên trang hạn chế, trên ASP NET trang (làm việc với ASP .NET 3.5) Tôi có thể có nhiều nút gửi biểu mẫu giống nhau, và dựa trên thông tin tiêu đề nộp Trang biết mà kiểm soát (Button) kích hoạt trình hình thức, và phương pháp chính xác có thể được gọi trên máy chủ (phương pháp gắn liền với sự kiện Click Button).

Nếu tôi sử dụng giải pháp từ StackOverflow câu trả lời khác, ví dụ:

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

không xử lý sự kiện sẽ được kêu gọi PostBack. Nếu tôi thay thế bằng:

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

nó sẽ dẫn đến việc đệ quy hộp thoại vô tận. Làm thế nào để giải quyết nó trong ASP .NET?

Trả lời

1

Tôi phải giải quyết câu hỏi này cách đây vài tháng.Tôi muốn có nhiều nút trên biểu mẫu, có thể trên nút hủy cộng với bộ lặp được tạo mẫu và yêu cầu tất cả chúng yêu cầu xác nhận phù hợp và gửi biểu mẫu hoặc hủy dựa trên hành động của người dùng. Kiểm soát dưới đây có thể được đưa vào một biểu mẫu nhiều lần nếu cần. Nó được kế thừa từ System.Web.UI.WebControls.LinkButton và sử dụng PostbackEventReference của kiểm soát để biết cần phải kiểm soát điều gì nếu được xác nhận. Kiểm soát có thể dễ dàng kế thừa từ System.Web.UI.WebControls.Button thay vào đó nếu bạn muốn. Tôi đã chọn sử dụng nút liên kết vì nút này hoạt động rất giống với nút điều khiển web nhưng không phát ra <input type=submit> không thể được tạo kiểu bằng biểu tượng bằng cách sử dụng jQuery UI mà không sử dụng bộ điều khiển.

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

Tôi đã đưa ra công việc này khoảng một thời gian trở lại vì vậy không chắc chắn nếu nó vẫn cập nhật với các plugin jquery-ui mới nhất nhưng bạn có được ý tưởng chung. Nó làm cho (không may) sử dụng eval để thực thi javascript asp.net tạo ra để gửi biểu mẫu được đặt trong href của neo. Bạn chỉ cần cung cấp cho neo lớp css của 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> 
3

Là một lựa chọn: sử dụng SubmitBehavior="false" cho Nút điều khiển và địa điểm kịch bản dưới đây trước khi thẻ đóng dạng của:

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

Nếu bạn muốn gọi xác nhận explicitely chỉ cho các nút cụ thể, bạn có thể sử dụng kịch bản dưới đây (có thể được đặt trong tiêu đề)

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)" /> 
+0

này sẽ chạy ở bất kỳ postback, tuy nhiên, không nhất thiết chỉ trên trình mẫu do nút gửi. Bất cứ điều gì gây ra postback đầu tiên sẽ được dừng lại và xác nhận. – dwerner

1

Tôi đã sử dụng gần đây, mặc dù nó chỉ hoạt động với nút liên kết. Bạn có thể tạo kiểu cho chúng (chúng chỉ là các neo) để trông giống như các nút html nếu bạn muốn.

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 đánh dấu (confirmMe_Click Sự kiện này sẽ được nâng lên nếu bạn bấm ok)

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

+1 preventDefault() thường bị lãng quên. \ – dwerner

0

Tôi thừa nhận đó là một chút dài, nhưng các công trình sau đây cho mọi trường hợp tôi có thể nghĩ của:

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

Đã kiểm tra đánh dấu sau bằng cách sử dụng ASP.Net 4.0 Framework với jQuery 1.8.2 và 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> 
0

Đó là hai xu của tôi, mà làm việc cho dự án của tôi:

// 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'); 
     }); 
    }); 
Các vấn đề liên quan