[ASP.NET] Submit a un iFrame dentro de la misma pagina. Con PostbackUrl y modificando el target del formulario (JS puro y jQuery)

Por una pregunta sobre este tema “Enviar datos a una forma dentro de un iframe”, desempolve algo que tenia en borrador hace años…

ANTES NADA… Por qué lo tenia en borrador?

Pense que nadie lo necesitaba… Porque trabajar con iFrames en ASP.NET Webforms en “un dolor constante”, hay que hacer cosas con javascript para la comunicación… una tema fácil es incrustar desde ASP.NET contenido en iframes, y otra es enviar-recibir información. Todo esto porque la magia es ASP.NET es tener un solo formulario que casi casi no debes “tocarlo”

(NOTA: en ASP.NET MVC es una maravilla trabajar con javascript, tienes un mejor control del HTML resultante)

En ASP.NET Webforms tenemos varias opciones a los iFrames para “cargar contenido”

 

Pero volvamos al tema de enviar datos a una iFrame dentro de la misma pagina…

 

El problema

Al problema que en los foros de MSDN preguntaron tenia era como eje esta misma temática así que aquí va para tenerla de referencia.
“Enviar datos a una forma dentro de un iframe”, que como sabemos en ASP.NET tenemos un solo formulario en las paginas, en cada postback se realiza un post a la misma pagina salvo que cambiemos en un boton por ejemplo la propiedad PostbackUrl para modificar la pagina donde enviara los datos… pero no podemos definir el target (nombre del frame) de donde queremos que cargue la pagina destino.

Solución

Para que funcione necesitamos en ASP.NET webforms o en cualquier otro formulario web modificar el atributo target del formulario

Solución en ASP.NET Webforms

Como modificamos la pagina de destino para enviar los datos? con la propiedad PostbackUrl.
Como modificamos el target del formulario? en el cliente lo tenemos que hacer al momento de realizar el click… del boton. Nos ayudamos con OnClientClick

Bueno para muestra “basta un botón” así que el ejemplo para descargar image

 

La pagina padre

Default.aspx

Ingrese un Nombre: <asp:TextBox ID="txtNombre" runat="server" ClientIDMode="Static"></asp:TextBox>
<asp:Button ID="btnAceptar" runat="server" Text="Aceptar" OnClientClick="enviarDatosAFrame('iframePaginaHija');" PostBackUrl="~/PaginaIframeDestino.aspx" />
<iframe id="iframePaginaHija" name="iframePaginaHija" src="PaginaIframeDestino.aspx" width="100%" height="200px"></iframe>
<p>&nbsp;</p>
<asp:Label ID="lblHora" runat="server" Text="lblHora"></asp:Label>

Si podemos ver el botón que es un webcontrol Button que tiene dos atributos definidos

  • OnClientClick: Que nos ayuda a llamar a una funcion del lado del cliente antes de enviar el submit
  • PostbackUrl: Nos ayuda a definir una pagina de destino diferente a la actual cuando se realice el submit

Tenemos un script llamado “enviarDatosAFrame” que es una función del lado del cliente en javascript que nos ayuda a cambiar el atributo target del formulario de ASP.NET

<script type="text/javascript">
    function enviarDatosAFrame(frameNombre) {
        var formulario = document.getElementById('form1');
        formulario.target = frameNombre;

        setTimeout('formularioInicializar(\'' + formulario.id + '\');', 2000);
    }         
</script>
Mas adelante vemos que es el formularioInicializar.

NOTA: Para que nos sirva de esta manera que buscamos el formulario por Id (getElementById), debes tener definido el Id del formulario de ASP.NET (de tu pagina o MasterPage)

 
 
 

La pagina destino (el contenido del iframe)

PaginaIframeDestino.aspx (en el ejemplo)

Nombre: <asp:Label ID="lblNombre" runat="server" Text="lblNombre"></asp:Label>
<p>&nbsp;</p>
<asp:Label ID="lblHora" runat="server" Text="lblHora"></asp:Label>

Tengo definido en la pagina la directiva PreviousPageType para tener intellisense de lo voy a obtener de la pagina padre

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="PaginaIframeDestino.aspx.cs" Inherits="PaginaIframeDestino" %>
<%@ PreviousPageType VirtualPath="~/Default.aspx"  %>


En el codebehind…

protected void Page_Load(object sender, EventArgs e)
   {
       if (PreviousPage != null)
       {
           //Sin el atributo de pagina PreviousPageType 
           //TextBox txt = (TextBox)PreviousPage.FindControl("txtNombre");
           //string nombre = txt.Text;

           //Con el atributo de pagina PreviousPageType, 
           //tenemos acceso a intellisense de PreviousPage (que agregamos una propieddad publica) 
           string nombre = PreviousPage.Nombre;


           lblNombre.Text = nombre;
       }

       lblHora.Text = DateTime.Now.ToLongTimeString();
   }

 

NOTA en la pagina padre (default.aspx) tengo una propiedad para recuperarla en la destino

public partial class _Default : System.Web.UI.Page
{
    public string Nombre {
        get {
            return txtNombre.Text;
        }
    }
...

 

Colocar el atributo target directamente en el form? por si lo pensaste colocar aquí…

Hacer esto significaría que todo postback de esa pagina tendrá como target el definamos “estáticamente allí”… si lo hacemos con javascript a este cambio será dinámico y solamente hay que agregar al control que hace el sumbit la funcionalidad de que ejecute, previo submit, el cambio de target

image

 

 

Con JQuery: Agregar funcionalidad no intrusiva en botón

Con la ayuda de jQuery podemos armar una función que nos ayude a la tarea de modificar el target del formulario a partir de la configuración de un botón si necesidad de adicionar OnClientClick sino simplemente configurando el botón con unos atributos

En este ejemplo, para probar los atributos data de jQuery, se me ocurrió utilizar data-FrameDestino para definir el nombre del iframe donde quiero enviar los datos y como todavía no se como es el selector para “data”, utilice un selector de clase css, entonces todos los botones con la clase “postbackToFrame” tendrán esta funcionalidad

El botón queda así:

<asp:Button ID="btnAceptarConjQuery" runat="server" Text="Aceptar (con jQuery)" 
        PostBackUrl="~/PaginaIframeDestino.aspx" 
        CssClass="postbackToFrame" 
        data-frameDestino="iframePaginaHija" />

La función jQuery

<script type="text/javascript">
    $(document).ready(function () {
        $(".postbackToFrame").click(function () {
            var form = $(this).parents("form:first");
            var formNombre = $(form).attr("id");
            var frameNombre = $(this).data("frameDestino");
            if (frameNombre != null || frameNombre != 'undefined') {

                $(form).attr('target', frameNombre);
            }

            setTimeout('formularioInicializar(\'' + formNombre + '\');', 2000);
        });
    })
</script>

Mas adelante vemos que es el formularioInicializar…

 

Modificamos el target del form, pero las siguientes acciones toman el mismo camino. Como inicializamos?

Cuando modificamos en el cliente el target del formulario el mismo permanece allí y cualquier otra acción que involucre un postback se dirigirá al target correspondiente. Si en la pagina tenemos mas botones, linkbutton o cualquier control que realice un submit tomara el valor del formulario que configuramos

Si llegamos a necesitar que el valor del target se inicialice debemos llamar a una función para tal motivo luego de un tiempo prudencial del submit, en mi caso 2000 milisegundos

Con jQuery

<script type="text/javascript">
    function formularioInicializar(formularioNombre) {
        $('#' + formularioNombre).attr('target', '');
    }      
</script>

O como la primer versión con javascript puro.

<script type="text/javascript">
    function formularioInicializar(formularioNombre) {
        var form = document.getElementById(formularioNombre);
        formt.target ='';
    }      
</script>
 
NOTA: Seria bueno este inicializar formulario reciba el target tambien y podemos unificar todas las funciones que modifican este atributo
 
 

Ejemplo para descargar

 

Espero que les sirva de ayuda o guía.

Crossposting desde mi blog en Geeks.ms: http://geeks.ms/blogs/fernandezja

Published 03-26-2011 14:12 por Jose A. Fernandez