2012-10-19 19 views
6

Próbuję wykorzystać zalety jQuery UI (lub dowolnej innej wtyczki dialogowej), aby zastąpić domyślne okno dialogowe Potwierdź. Są tam wiele podobnych pytań i odpowiedzi na StackOverflow, na przykład:Jak używać okna dialogowego jQuery UI jako okna dialogowego "potwierdź przed przesłaniem" na ASP.NET formularz

jquery dialog: confirm the click on a submit button

Jednak w ASP .NET Potrzebuję czegoś więcej.

Ze względu na jeden formularz na stronie przymusu, na stronie ASP .NET (współpracuje z ASP .NET 3.5) mogę mieć wiele przycisków, które złożą taką samą formę, i na podstawie przedstawionych informacji nagłówka strona wie, które sterowanie (Button) wyzwoliło przesłanie formularza, a poprawną metodę można wywołać na serwerze (metoda dołączona do zdarzenia Click Button).

Jeśli używam rozwiązanie od innych odpowiedzi StackOverflow, na przykład:

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

bez obsługi zdarzeń będzie wywoływana na odświeżenie strony. Jeśli zamieniam je na:

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

spowoduje to nieskończoną rekursję dialogów modalnych. Jak rozwiązać ten problem w ASP .NET?

Odpowiedz

1

Musiałem rozwiązać to pytanie kilka miesięcy temu.Chciałem mieć wiele przycisków na formularzu, być może na przycisku anulowania i dołączonym do szablonowego przekaźnika, i wszystkie poprawnie poprosić o odpowiednie potwierdzenie i albo przesłać formularz, albo anulować w oparciu o akcję użytkownika. Poniższy formularz kontrolny można umieścić w formularzu tyle razy, ile to konieczne. Dziedziczy on od System.Web.UI.WebControls.LinkButton i używa kontrolki PostbackEventReference, aby wiedzieć, która kontrola ma zostać przesłana, jeśli została potwierdzona. Kontrola może łatwo zastąpić od System.Web.UI.WebControls.Button, jeśli wolisz. Wybrałem opcję użycia przycisku łącza, ponieważ działa on bardzo podobnie do kontrolki internetowej przycisku, ale nie emituje ikony <input type=submit>, której nie można stylizować za pomocą ikon wykorzystujących interfejs użytkownika jQuery bez użycia adaptera kontrolnego.

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

Wpadłem z tą pracą jakiś czas temu, więc nie jestem pewien, czy jest ona wciąż aktualna z najnowszą wtyczką dialogową jquery-ui, ale masz ogólny pomysł. To sprawia, że ​​(niefortunne) użycie eval do wykonania javascript asp.net generuje do przesłania formularza, który jest umieszczony w href kotwicy. Musisz tylko dać kotwicy klasę css 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

Jako opcja: wykorzystać SubmitBehavior="false" do kontroli przycisk i miejsce skryptu poniżej przed formularza zamykającym tagiem:

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

Jeśli chcesz zadzwonić potwierdzenie jawnie tylko dla poszczególnych przycisków, można wykorzystać skrypt poniżej (może być umieszczone w nagłówku)

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

ten będzie działał w każdym odświeżenie strony, choć niekoniecznie tylko o poddaniu formie przez przycisk Wyślij. Wszystko, co powoduje odświeżenie, zostanie najpierw zatrzymane i potwierdzone. – dwerner

1

Użyłem tego ostatnio, mimo że działa tylko z przyciskiem linku. Możesz je stylować (to przecież tylko kotwice), żeby wyglądały jak przyciski html, jeśli chcesz.

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 znaczników (confirmMe_Click zdarzenie zostanie podniesiony po kliknięciu OK)

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

+1 preventDefault() jest często zapomniany. \ – dwerner

0

muszę przyznać, że to trochę długie, ale następujące prace w każdym przypadku mogę myśleć z:

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

Testowane na następujących znacznikach przy użyciu ASP.Net 4.0 Framework z jQuery 1.8.2 i 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

To są moje dwa centy, które pracowały dla mojego projektu:

// 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'); 
     }); 
    }); 
Powiązane problemy