Popup y retorno de valores con MVC 4 + bootstrap

En esta ocasión vamos a mostrar un pequeño ejemplo de cómo abrir un popup con MVC 4 y cómo hacer para generar un valor (o varios) de retorno a la página principal.

Voy a generar una grilla con GRIDMVC y todo el diseño y manejo del popup lo hago con bootstrap 3.0 +. Para descargarlo en el sitio tenemos que hacer esto.

foto1

foto2

foto3

En nuestro Controller vamos a generar una pequeña lista para llenar la grilla.

public class TestController : Controller
    {
        //
        // GET: /Test/

        private readonly  List clients = new List()
        {
            new Client { Id = 1, Name = "Julio Avellaneda", Email = "julito_gtu@hotmail.com" },
            new Client { Id = 2, Name = "Juan Torres", Email = "jtorres@hotmail.com" },
            new Client { Id = 3, Name = "Oscar Camacho", Email = "oscar@hotmail.com" },
            new Client { Id = 4, Name = "Gina Urrego", Email = "ginna@hotmail.com" },
            new Client { Id = 5, Name = "Nathalia Ramirez", Email = "natha@hotmail.com" },
            new Client { Id = 6, Name = "Raul Rodriguez", Email = "rodriguez.raul@hotmail.com" },
            new Client { Id = 7, Name = "Johana Espitia", Email = "johana_espitia@hotmail.com" }
         };

        
        public ActionResult Index()
        {
              return View(clients);
        }
        public ActionResult AbrirPopup()
        {
           return View("Popup");
        }
    }

HTML de página de inicio (donde vamos a poner nuestra grilla y todo el manejo del popup con bootstrap)

@model IEnumerable<MVCEmpty.Models.Client>
@using GridMvc.Html

@{
    ViewBag.Title = "Index";
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    
     <link href="@Url.Content("~/Content/bootstrap.min.css")" rel="stylesheet" />
    
    <script src="@Url.Content("~/Scripts/jquery-1.11.1.min.js")"></script>
    <script src="@Url.Content("~/Scripts/bootstrap.js")"></script>
    <script src="@Url.Content("~/Scripts/bootbox.min.js")"></script>


   <script src="@Url.Content("~/Scripts/gridmvc.min.js")"></script>
   <link href="@Url.Content("~/Content/Gridmvc.css")" rel="stylesheet" />
  
    <title>Index</title>
</head>

  

<body>
    <h1>Prueba de Modales</h1>
    <hr />

    <script>


        //function OpenModalBoostrap() {
        //    var trigger = $("body").find('[data-toggle="modal"]');

        //    trigger.click(function () {
        //        var theModal = $(this).data("target"),
        //        videoSRC = $(this).attr("data-Source"),
        //        videoSRCauto = videoSRC;
        //        $(theModal + ' iframe').attr('src', videoSRCauto);

        //        $(theModal + ' button.close').click(function () {

        //            $(theModal + ' iframe').attr('src', videoSRC);
        //        });
        //    });
        //}




        function AbrirModal() {
            var trigger = $("body").find('[data-toggle="modal"]');
            

            trigger.click(function (e) {
                e.preventDefault();
                var SRCpaginaModal = $(this).attr("data-source");
                var valorIDenAtributo = $(this).attr("data-id");
                //alert(valorIDenAtributo);

                    $("#videoModal" + ' iframe').attr('src', SRCpaginaModal);

                    // finally, wire up the actual modal functionality and show the dialog
                    $("#videoModal").modal({
                        "backdrop": "static",
                        "keyboard": false,
                        "show": true // this parameter ensures the modal is shown immediately
                    });


                    //Evento que atrapa cuando se cierra el modal.
                    $('#videoModal').on('hidden.bs.modal', function () {
                      //  alert("se cierra desde pagina principal");
                    })
                    
            });

        }

                //        });

           $(function () {

               // OpenModalBoostrap();
               AbrirModal();
                    @*  $('.popup-modal').magnificPopup({
                         items: [{
                               src: '@Url.Action("AbrirPopup","Popup")',
                               type: 'iframe', // this overrides default type
                               preloader: false,
                               modal: true
                           }]
                     });

                    $(document).on('click', '.popup-modal-dismiss', function (e) {
                        e.preventDefault();
                        $.magnificPopup.close();
                    });*@


               window.onmessage = function (e) {
                   //Recibo el mensaje 
                   var DataReceived = e.data;
                   var OriginUrl = e.origin;

                   
                   MostrarReturnFromModal(DataReceived);
                  
                   }


                });

        function MostrarReturnFromModal(msj) {
            $('#alert_placeholder').empty();
            $('#alert_placeholder').append('<div class="alert alert-block alert-info fade in"><h4>Valor devuelto!</h4>' + msj + '</div>');
            //$('#alert_placeholder').append('<span class="label label-info">El valor devuelto es: <br/>' + msj + '</span>');
            
            $('#alert_placeholder').show();
            alertTimeout(2500); //and here
        }

        function alertTimeout(wait) {
            setTimeout(function () {
                //$('#alert_placeholder').children('.alert:first-child').remove()
                $('#alert_placeholder').hide()
            }, wait);
        }
            //});

</script>

    


    <div style="width:700px;">
        @Html.Grid(Model).Columns(columns => 
                    {
                        //columna 1
                        columns.Add(c => c.Id, true).Titled("Client ID");

                        //columna 2
                        columns.Add(c => c.Name).Titled("Name")
                            .Sanitized(false)
                            .Encoded(false)

                            /*
                             * MODO DE GENERAR EL ELEMENTO <A>:
                             * dejando en el href --># 
                             * y en el data-soruce le agrego el url.action seguido de los parametros que se deseen. El mismo Controller sera el encargado de encriptarlos
                             *       .RenderValueAs(o => Html.ActionLink(((string)o.Name),  null,null,
                                                               null,
                                                                new {   href="#" ,
                                                                        data_toggle="modal" ,
                                                                        data_source = @Url.Action("AbrirPopup", "Popup", new { id = (int)o.Id }),
                                                                        data_id = (int)o.Id }).ToHtmlString());
                             * el atributo data_id tambien tiene el ID del elemento
                             */
                            .RenderValueAs(o => Html.ActionLink(((string)o.Name),  "AbrirPopup", "Popup",
                                                                new { id = (int)o.Id }, /*Nose para que estoy, pero si me sacas no llego ni a la paternal*/
                                                                new {   href="#" ,  /*SIN ESTO NO VIVIMOS*/
                                                                        data_toggle="modal" , /*toggle necesario para que funcione el bootstrap*/
                                                                        data_source = @Url.Action("AbrirPopup", "Popup", /*Ruta a donde esta el popup*/
                                                                /*zona de parametros*/
                                                                new {   id = (int)o.Id, 
                                                                        otro_atributo = (string)o.Email }),
                                                                        data_id = (int)o.Id }).ToHtmlString());
                            
                        
                        //columna 3
                        columns.Add(c => c.Email).Titled("Email");
                    }).WithPaging(3).Sortable(true)
    </div>



@*
    <!-- Button that triggers the popup -->
            <button id="my-button">POP IT UP</button>
            <!-- Element to pop up -->
            <div id="element_to_pop_up">Content of popup</div>

*@



    

    

    


    
    <!--data-keyboard="false"  con esto evito que cierre el modal cuando toca ESC-->
    <!--data-backdrop= 'static'  con esto evito que cierre el modal cuando da click afuera-->
    <!--data-id= con esto puedo incrustarle valores al elemento <a> para poder pasarlo como parametro-->
@*    <a href="#" class="btn btn-default" data-toggle="modal" data-target="#videoModal" 
                    data-keyboard="false" 
                    data-backdrop= 'static' 
                    data-Source="@Url.Action("AbrirPopup","Popup", new { id=2})" >Modal Boostrap</a>*@

@*        <a href="#" class="btn btn-default" data-toggle="modal" data-id="1522"
            data-source="@Url.Action("AbrirPopup","Popup", new { id=2})" >Modal Bootstrap</a>*@


<div class="modal fade" id="videoModal" tabindex="-1" role="dialog" aria-labelledby="videoModal" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
        <div>
          <a href=""></a>
            
        </div>
      </div>
    </div>
  </div>
</div>

    <div id="alert_placeholder"></div>
    <input type="hidden" id="valorOculto" value="0" />
</body>
</html>

Vamos a ir explicando de a poco todo el código anterior:

1ero la generación de la grilla.

    <div style="width:700px;">
        @Html.Grid(Model).Columns(columns => 
                    {
                        //columna 1
                        columns.Add(c => c.Id, true).Titled("Client ID");

                        //columna 2
                        columns.Add(c => c.Name).Titled("Name")
                            .Sanitized(false)
                            .Encoded(false)

                            /*
                             * MODO DE GENERAR EL ELEMENTO <A>:
                             * dejando en el href --># 
                             * y en el data-soruce le agrego el url.action seguido de los parametros que se deseen. El mismo Controller sera el encargado de encriptarlos
                             *       .RenderValueAs(o => Html.ActionLink(((string)o.Name),  null,null,
                                                               null,
                                                                new {   href="#" ,
                                                                        data_toggle="modal" ,
                                                                        data_source = @Url.Action("AbrirPopup", "Popup", new { id = (int)o.Id }),
                                                                        data_id = (int)o.Id }).ToHtmlString());
                             * el atributo data_id tambien tiene el ID del elemento
                             */
                            .RenderValueAs(o => Html.ActionLink(((string)o.Name),  "AbrirPopup", "Popup",
                                                                new { id = (int)o.Id }, /*Nose para que estoy, pero si me sacas no llego ni a la paternal*/
                                                                new {   href="#" ,  /*SIN ESTO NO VIVIMOS*/
                                                                        data_toggle="modal" , /*toggle necesario para que funcione el bootstrap*/
                                                                        data_source = @Url.Action("AbrirPopup", "Popup", /*Ruta a donde esta el popup*/
                                                                /*zona de parametros*/
                                                                new {   id = (int)o.Id, 
                                                                        otro_atributo = (string)o.Email }),
                                                                        data_id = (int)o.Id }).ToHtmlString());
                            
                        
                        //columna 3
                        columns.Add(c => c.Email).Titled("Email");
                    }).WithPaging(3).Sortable(true)
    </div>

Con el método Html.ActionLink puedo generar un HTML donde voy a poner toda la funcionalidad de bootstrap. Es muy importante recordar poner el href=”#” para que al hacer click al link no vaya directamente a la página, sino que sea bootstrap quien dispare el popup.
El atributo data_toggle=”modal” es el que necesita bootstrap para que reconozca el link.
El data_source queda formado con un @Url.Action donde le indico que vaya a Popup/AbrirPopup (pasando previamente por mi Controller de Popup)

2do Contenedor del popup
Es muy importante ver que en la página madre vamos a tener el contendor vacio del popup que con bootstrap vamos a llenar via iframe. El tamaño de este contenedor se puede establecer, dejo el HTML:

<div class="modal fade" id="videoModal" tabindex="-1" role="dialog" aria-labelledby="videoModal" aria-hidden="true">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-body">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
        <div>
          <a href=""></a>
            
        </div>
      </div>
    </div>
  </div>
</div>

3ero la funcion de JS

La función que dispara el popup. Hay que recalcar aqui el evento que atrapa el mensaje de vuelta.

        function AbrirModal() {
            var trigger = $("body").find('[data-toggle="modal"]');

            trigger.click(function (e) {
                e.preventDefault();
                var SRCpaginaModal = $(this).attr("data-source");
                var valorIDenAtributo = $(this).attr("data-id");
                //alert(valorIDenAtributo);

                    $("#videoModal" + ' iframe').attr('src', SRCpaginaModal);

                    // finally, wire up the actual modal functionality and show the dialog
                    $("#videoModal").modal({
                        "backdrop": "static",
                        "keyboard": false,
                        "show": true // this parameter ensures the modal is shown immediately
                    });


                    //Evento que atrapa cuando se cierra el modal.
                    $('#videoModal').on('hidden.bs.modal', function () {
                      //  alert("se cierra desde pagina principal");
                    })
                    
            });

        }

           $(function () {

               // OpenModalBoostrap();
               AbrirModal();
                    
               window.onmessage = function (e) {
                   //Recibo el mensaje 
                   var DataReceived = e.data;
                   var OriginUrl = e.origin;
                   MostrarReturnFromModal(DataReceived);
                   }
                });

De acá es importante observar la manera que utilizo para intercambiar mensajes entre las 2 páginas. Luego voy a mostrar como lo envío.

 window.onmessage = function (e) {
                   //Recibo el mensaje 
                   var DataReceived = e.data;
                   var OriginUrl = e.origin;
                   MostrarReturnFromModal(DataReceived);
                   }

El siguiente paso es ver nuestro Controller de Popup. La ventaja de MVC es que me permite tener una sola clase que administre TODOS los popup que pueda generar mi sitio. De esta manera podemos reutilizar mucho código.

 
public class PopupController : BaseController
    {
       public ActionResult Index()
        {
            return View();
        }
       public ActionResult AbrirPopup(string Id, string otro_atributo)
        {
            QSQueryString valor = base.GenerarQS(new KeyValuePair&lt;string, string&gt;("Id", Id),
                                                 new KeyValuePair&lt;string, string&gt;("valor", otro_atributo));
            ViewData["MyProduct"] = valor;

            return View("Popup");
        }
    }

Lo único de especial aquí es que tengo una clase, llamada GSQueryString, que me genera parámetros. Más adelante voy a desarrollar un código que encripte esos parámetros para darle mayor seguridad al sitio. Por ahora están en texto plano.

Y por ultimo me resta mostrar el javascript que necesita el popup para funcionar. Aqui lo importante es la linea que me envia datos a la pagina principal.

       @{
        var prod = (QSQueryString)ViewData["MyProduct"];
    }

<script type="text/javascript">
       $(function () {
           $('#buttonPopup').click(function () {

               //para cerrar el popup desde adentro del mismo uso esto.
               if (window.parent == window.top) {
                   //alert($('#Retorno').val()); //valor del textbox
                   //alert(window.parent.$(valorOculto).val()); //esto no funca
                   //alert("se cierra desde modal");


                   var curDomain = location.protocol + '//' + location.host; //This will be received as e.origin (see above)
                   var commandString = $('#Retorno').val(); //This will be received as e.data
                   parent.postMessage(commandString, curDomain); //ESTO ME PERMITE ENVIARLE DATOS A LA PAGINA MADRE
                   window.parent.$('#videoModal').modal('hide');
               }
                
            });
       });
</script>

Por ultimo dejo algunas imágenes de cómo funciona el ejemplo y adjunto un link a Google Drive para que se pueda descargar.
Saludos.
Dudas, preguntas, comentarios tambien pueden dejarlos en trytocatch.arg@gmail.com

foto4

foto5

foto6

LINK A GOOGLE DRIVE
La contraseña es: https://trytocatch.wordpress.com

Anuncios

2 comentarios sobre “Popup y retorno de valores con MVC 4 + bootstrap

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s