miércoles, 2 de septiembre de 2009

Asp.Net: ModalPopupExtender y evento onclick

Estaba implementando el control ModalPopupExtender pero quería que al presionar el botón que establecí para el atributo OkControlID, hiciera una tarea específica, por ejemplo, que actualice la propiedad Text de un Label. (El atributo CancelControlID también esta presente en el control ModalPopupExtender).

Ya existía del lado del servidor un código que se debía ejecutar cuando hago clic en dicho botón. El problema es que no se estaba ejecutando ese código. El código XHTML para el modalpopup es el que se muestra a continuación:


<div id="modalMsg" style="border: 0.01em dotted brown; display: none; width: 320px; height: 80px;">
<span style="font-weight: bold; margin-bottom: 20px;">¿Seguro que desea eliminar el
registro?</span>
<div>
<asp:button id="btnSi" runat="server" text="Sí" onclick="Msg()">
<asp:button id="btnNo" runat="server" text="No">
</asp:button></asp:button></div>
</div>

También se observan los botones btnSi y btnNo. Veamos que el atributo onclick está presente. Lo puse para ejecutar en el lado del cliente una simple función de ejemplo.

Para empezar, el atributo onclick en un botón del lado del servidor, no es compatible con controles del tipo "Web Serve Control". Lo que se debe usar es el atributo OnClientClick.
Si fuera un botón Html si funcionaría. Si yo dejo el onclick aparecerá un error indicando que la función Msg() no es parte del archivo ASP.default_aspx'. Por lo tanto, en vez de onclick hay que usar OnClientClick.

Pero aun queda el problema de que no se está ejecutando el método del lado del servidor. El código para el botón btnSi es el siguiente:
Protected Sub btnSi_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSi.Click
lblResultado.Text = "Hizo clic en el botón 'Sí'"
End Sub
El objetivo es que ese método del lado del servidor se ejecute sin problemas; es evidente que al usar ModalPopupExtender, dicha funcionalidad se pierde.

La solución es usar el atributo OnClientClick más una función que ejecute el método __doPostBack:
<div id="modalMsg" style="border: 0.01em dotted brown; display: none; width: 320px; height: 80px;">
<span style="font-weight: bold; margin-bottom: 20px;">¿Seguro que desea eliminar el
registro?</span>
<div>
<asp:button id="btnSi" runat="server" text="Sí" onclientclick="server('btnSi')">
<asp:button id="btnNo" runat="server" text="No" onclientclick="server('btnNo')">
</asp:button></asp:button></div>
</div>

<script type="text/javascript">
function server(arg) 
{
 __doPostBack(arg, '');
}
</script>

No obstante existe otra solución. Ya dijimos que los atributos OkControlID y CancelControlID se están utilizando. La segunda solución sería eliminar esos atributos del todo y listo, no es necesario hacer nada más.

En caso de que el Label este dentro de un control UpdatePanel, se debe registrar en el evento Page_Load el botón btnSi con:

ScriptManager1.RegisterAsyncPostBackControl(btnSi)

Eso hará que el Label se actualice asíncronamente si tener que refrescar toda la página. Un equivalente es registrar un Trigger para el botón dentrol del UpdatePanel.

Referencias:
Asp.Net Ajax

1 comentario:

Anónimo dijo...

Muy buen articulo, gracias¡¡¡