Autor en Google+
Saltar al contenido

Variable not found. Artículos, noticias, curiosidades, reflexiones... sobre el mundo del desarrollo de software, internet, u otros temas relacionados con la tecnología. C#, ASP.NET, ASP.NET MVC, HTML, Javascript, CSS, jQuery, Ajax, VB.NET, componentes, herramientas...

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, noticias, curiosidades, reflexiones... sobre el mundo del desarrollo
de software, internet, u otros temas relacionados con la tecnología

¡Microsoft MVP!
miércoles, 28 de noviembre de 2007
De vez en cuando reviso las palabras por las que se llega a Variable Not Found a través de los buscadores, más que nada porque suelen reflejar dudas o problemas comunes de los desarrolladores y pueden servir como inspiración sobre nuevos temas a tratar en el blog.

Pues bien, llevo tiempo observando que hay muchas personas que preguntan a Google algo similar a "anular postback en botón", es decir, se tienen dudas sobre cómo evitar el disparo del postback al pulsar un botón de un formulario ASP.Net. El tema me ha parecido tan interesante que intentaré dar una respuesta a la duda estudiando algunas de las distintas posibilidades que pueden darse. Eso sí, si echáis en falta algún caso, no dudéis en comentarlo y lo trataremos lo antes posible.


I. ¿Hablamos de botones con lógica exclusivamente en cliente?

La primera cuestión es preguntarse para qué queremos un botón que no realice un postback al ser pulsado. Pensad que si todas las acciones desencadenadas por la pulsación del botón se realizarán en cliente es posible que no necesitemos un control ASP.Net. Imaginemos, por ejemplo, un botón que queremos que haga un cálculo en el cliente y muestre un cuadro de alerta con el resultado... ¿es necesario que sea un control de servidor (runat="server")? Seguro que no.

Para este caso lo más apropiado es incluir en el .aspx un HTML INPUT de los de toda la vida:

<input id="Button1" type="button" value="button"
onclick="hacerAlgo();" />
 
Si eres de los que prefieren arrastrar y soltar, puedes hacer exactamente lo mismo utilizando los controles incluidos en la pestaña HTML de Visual Studio, en este caso el llamado Input(Button). El resultado visual será idéntico al de un Button (un botón de servidor) y estaremos aligerando tanto la página enviada al cliente como la carga del servidor.

II. Anular el postback en un botón de servidor

Otra posibilidad es que vayas a usar un control de servidor (un Button, por ejemplo) y sólo bajo determinadas circunstancias quieras anular el postback desde el cliente. Obviamente, estas circunstancias serían calculadas/obtenidas por script, por lo que podríamos aplicar un patrón como el siguiente:

...
<asp:Button ID="Button1" runat="server"
Text="Pulsa"
OnClientClick="return comprueba();" />
...
<script type="text/javascript">
function comprueba() {
return confirm("Confirme el postback");
}
</script>
 
Como se puede observar, se ha modificado la propiedad OnClientClick del botón para hacer que retorne el resultado de la llamada a la función comprueba(). Si ésta retorna cierto, se realizará el postback, mientras que si retorna falso, no lo hará. En el ejemplo anterior se permite al usuario decidir si desea enviar el formulario al servidor o no.

III. Anular la posibilidad de envíos múltiples

Hay otras ocasiones, sin embargo, en las que estamos utilizando un botón de servidor de forma normal y simplemente queremos evitar duplicidades en el envío del formulario, es decir, bloquear el botón correspondiente una vez el usuario lo haya pulsado la primera vez.

Esto es muy habitual debido a la falta de feedback: el usuario envía el formulario, se impacienta esperando la respuesta o no está seguro de haberlo enviado, y cual poseso, inicia un ataque implacable sobre el botón de envío. ¿A que os suena?

El comportamiento típico, adoptado por la mayoría de sitios web, es deshabilitar el botón y seguir con el postback. Sin embargo, esto que podría ser realmente sencillo mediante scripting, causa algún que otro problema cuando el botón es de tipo Submit, puesto que en determinados navegadores (por ejemplo IE6) no realizará el envío si lo está generando un botón deshabilitado. Una forma de evitar este problema es hacer que el botón no sea de tipo submit e incluir un pequeño script:

<asp:Button ID="Button2" runat="server"
Text="Pulsa"
OnClientClick="this.disabled=true"
UseSubmitBehavior="False"/>

Si el botón debe ser obligatoriamente de tipo submit, se deben utilizar soluciones alternativas. Googleando un poco he encontrado varias, como deshabilitar el botón pasadas unas décimas de segundo mediante un timer, o retocar los estilos del botón para, simplemente, hacerlo desaparecer y mostrar en su lugar un mensaje informativo. La mejor, para mi gusto, consiste en capturar el evento onsubmit del formulario web, así:

...
<form id="form1" runat="server" onsubmit="deshabilita()">
...
<script type="text/javascript">
function deshabilita()
{
var btn = "<%= Button1.ClientID %>";
if (confirm("Confirme postback"))
{
document.getElementById(btn).disabled = true;
return true;
}
return false;
}
</script>
 
Este último ejemplo lo he aprovechado para, además, mostrar cómo es posible realizar la captura del envío justo antes de que se produzca, en el evento OnSubmit, e introducir las confirmaciones de envío y deshabilitado de botones.

Publicado en Variable not found.

Estos contenidos se publican bajo una licencia de Creative Commons Licencia Reconocimiento-No comercial-Compartir bajo la misma licencia 3.0 España de Creative Commons

16 Comentarios:

Rub dijo...

Un artículo impecable :-) como suele suceder en este blog, felicidades y gracias por el artículo,

José M. Aguilar dijo...

Nada, un placer. ;-)

Y gracias a tí por el comentario.

Pamela dijo...

Hola José super bueno tu comentario, me sirvio mucho ya que apenas estoy empezando en el mundo de .net y el resto de articulos estan de lo mejor Medellin - Colombia...

→ Sharys Web dijo...
Este comentario ha sido eliminado por el autor.
rosario camargo dijo...

hola sr. aguilar, muy buen articulo, asi ya uno no utiliza el updatepanel, porq se le tiene miedo, entre mas cosas mas peligros...muchas gracias.

Ciberpato dijo...

No he podido hacer funcionar "Anular el postback en un boton de servidor" ya que al escribir el atributo OnClientClick no lo reconoce

Jorgelig dijo...

José no eh podido hacer funcionar tu segundo ejemplo, deshabilitar el boton despues del primer click.

No necesito confirmar, solo deshabilitar. El primer problema esque yo tengo el tag form en el MasterPage y un boton con el id: "btn_grabar", por lo que la linea donde le asignas el id la quite y puse directo el id en el string. La cosa esque no me funciona.

Tengo esto:
MasterPage:
aspx:
//en el head
**cript type="text/javascript">
function deshabilita_btn()
{
var btn = "btn_grabar";
document.getElementById(btn).disabled = true;
}
*/*cript>
//en el body
<*orm id="form1" runat="server" onsubmit="deshabilita_btn()">


aspx de uno de los formulario:
<*sp:Button ID="btn_grabar" runat="server" CssClass="cssboton" Text="Button"/>

Pd los * son intencionales, no me deja publicar html

José M. Aguilar dijo...

Hola, Jorge.

El escenario que planteas es algo más complejo. En primer lugar, el identificador del botón no sería "btn_grabar", pues ese es el nombre del control de servidor, pero no en cliente. De hecho, si miras en el código fuente de la página generada, verás que el id asignado al botón es algo como "ctl00_ContentPlaceHolder1_btn_grabar".

Para obtener el identificador en cliente tendrías que usar la propiedad ClientID del control de servidor, como en el último ejemplo (<%= btn_grabar.ClientID %>).

Sin embargo, el hecho de intentar introducir directamente esta operación en la MasterPage, provocará un error de compilación, puesto que ésta no es consciente de los controles que incluyen sus hijas, y en el primer acceso te dirá que el control no existe.

Tienes varias soluciones para este tema, pero la que creo más sencilla es añadir un ContentPlaceHolder en la sección <head> de la página maestra, y en el webform donde se encuentre tu botón incluir el script en dicho placeholder. En esa página sí podrás acceder al ClientID del control, y podrás implementar el script sin problema.

Espero que te sea de ayuda. :-)

Un saludo y gracias por comentar.

Anónimo dijo...

Lo que me gustaria saber es como hacer que ASP recuerde la posicion del formulario cuando hice clic en un boton que este asbajo en el fondo de la pagina. Es decir, que al refrescarse la pagina, no tenga que bajar con el scroll del raton de nuevo para ir a la posicion del form, para seguir metiendo datos.

David

José M. Aguilar dijo...

Hola.

Para conservar la posición de vertical de la página, puedes establecer la propiedad MaintainScrollPositionOnPostback="true" en la directiva @Page.

Saludos.

Maicol8k dijo...

despues de ver los resultados quiero hacer un nuevo registro.. presiono un boton y me sale un modalpopupextender.. y cuando estoy en el popup tengo un button que va agregando datos a un grid view.. pero ... solo me deja agregar uno , pues el popup desaparece y tengo que volver a cargar de nuevo si quiero seguir agregando cosas en la grilla del popup ...¿como hacer para que no se desvanesca el popup y seguir cargando mi gridview?

Anónimo dijo...

Hostia puta, despues de 5 horas investigando y probando con distintas opciones tan simple como la segunda solución que has dado, sencillamente genial. Ni document.getElementById('ctl00_PlaceHolderMain_DatosPersonalesControl_EliminarEmpleado');, ni obj.setAttributes(oncli...
ni WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions("ctl00$PlaceHolderMain$DatosPersonalesControl$EliminarEmpleado", "", true, "", "", false, false)), ni __doPostBack. Para hacer una llamada tras un confirm se añade en el onclick la llamada normal y en el onClientClick la llamada a return Confirmar() que devuelve la salida del confirm. Gracias, despues de 5 años sigue sirviendo el artículo ;)

José M. Aguilar dijo...

:-DD Genial!

Juan Carrasco Moya dijo...

Muchas gracias por el artículo. Hay que ver con lo fácil que era y lo complejo que resulta a veces encontrar esas cosas

Emerson Silva Toro dijo...

Hola resulta que tengo un botón en ASP y cuando le doy click y ejecuto esto: Response.Redirect("FrmBuscarNombreAlmacen.aspx"), pero por lo del postback me limpia los textbox del FrmBuscarNombreAlmacen.aspx y no se como ejecutar este mismo codigo ASP en un botón de HTML, podrias hacer un ejemplo de como ejecutar este mismo código en el botón HTML. Gracias viejo.

Frank Jhonnathan Vergara Vergara dijo...

Eso no sirve para nada, porque tengamos un caso que querramos procesar por el lado del servidor, pero deseamos validar del lado del cliente, dependiendo si pasa la validacion que permita el proceso del lado del servidor de caso contrario que no pase al servidor.