2012-10-19 17 views
6

Sto provando a sfruttare l'interfaccia utente jQuery (o qualsiasi altro plug-in di dialogo) per sostituire la finestra di dialogo Conferma predefinita. Ci sono un sacco domande simili e risposte su StackOverflow, per esempio:Come utilizzare la finestra di dialogo dell'interfaccia utente jQuery come finestra di dialogo "conferma prima dell'invio" sul modulo ASP .NET

jquery dialog: confirm the click on a submit button

Eppure, in ASP .NET ho bisogno di qualcosa di più.

causa una forma sulla pagina di vincolo, sulla pagina ASP .NET (che lavora con ASP .NET 3.5) Posso avere più pulsanti che presentano la stessa forma, e sulla base delle informazioni di intestazione presentate Pagina sa che invio di moduli trigger controllati (Button) e il metodo corretto può essere richiamato sul server (metodo collegato all'evento Click di Button).

Se uso la soluzione da altre risposte StackOverflow, per esempio:

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

nessun gestore di eventi saranno chiamati il ​​postback. Se lo sostituisco con:

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

risulterà in una ricorsione di dialogo modale infinita. Come risolverlo in ASP .NET?

risposta

1

ho dovuto risolvere questo problema qualche mese fa.Volevo avere più pulsanti su un modulo, magari su un pulsante Annulla più incluso in un ripetitore basato su modello, e chiedere a tutti loro di ottenere la conferma appropriata e inviare il modulo o annullare in base all'azione dell'utente. Il controllo sottostante può essere incluso in un modulo tutte le volte che è necessario. Esso eredita da System.Web.UI.WebControls.LinkButton e utilizza PostbackEventReference del controllo per sapere quale controllo inviare, se confermato. Il controllo può facilmente ereditare da System.Web.UI.WebControls.Button, se preferisci. Ho scelto di utilizzare un pulsante di collegamento perché funziona molto simile al controllo web del pulsante ma non emette <input type=submit> che non può essere abbinato a icone che utilizzano l'interfaccia utente di jQuery senza utilizzare un adattatore di controllo.

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

Sono uscito con questo lavoro un po 'indietro, quindi non sono sicuro se è ancora aggiornato con l'ultimo plugin di dialogo jquery-ui ma si ottiene l'idea generale. Rende (spiacevole) l'uso di eval per eseguire il javascript asp.net genera per inviare il modulo inserito nell'href dell'ancora. Hai solo bisogno di dare l'ancora la classe css di 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

In opzione: utilizzare SubmitBehavior="false" per controlli Button e luogo di script di seguito prima di tag di chiusura di forma:

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

Se si desidera chiamare conferma esplicitamente solo per particolari pulsanti, è possibile utilizzare lo script di seguito (può essere collocato nell'intestazione)

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

Questo verrà eseguito in qualsiasi postback, però, non necessariamente solo sul modulo di presentazione da parte del pulsante di invio. Tutto ciò che causa il postback verrebbe prima fermato e confermato. – dwerner

1

L'ho usato ultimamente, sebbene funzioni solo con un pulsante di collegamento. Puoi modellarli (sono solo ancore dopo tutto) per assomigliare ai pulsanti html, se lo desideri.

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 evento verrà generato se si fa clic su OK)

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

+1 preventDefault() è spesso dimenticato. \ – dwerner

0

Ammetto che è un po 'lunga, ma i seguenti lavori per tutti i casi mi viene in mente di:

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

Testato sui seguenti markup utilizzando il quadro ASP.Net 4.0 con jQuery 1.8.2 e 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

Questi sono i miei due centesimi, che ha lavorato per il mio progetto:

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