lunes, 30 de abril de 2012

[ASP.NET] PopUp Filtro – Usando jquery UI Dialog

 

Introducción

El objetivo del artículo apunta a demostrar como implementar la búsqueda de un determinado ítem haciendo uso de ventanas que se abran en popup.

Para implementarlo se hará uso de la librería jquery UI, la cual incluye funcionalidad para crear cuadros de dialog modales.

El código fue implementado de dos formas distintas, si bien son muy parecidas tienen sutiles cambios, estas dos formas las denomine:

  • Selección con evento (usando un ImageButton)
  • Selección sin evento  (usando el tag html <img>)

Imagino se preguntaran del porque de esta diferencia del uso de un evento o no, básicamente difieren en el uso de controles asp.net (con evento) o tag de html (sin evento), cada alternativa cambia la forma en que se implementa la solución, en concreto la forma en que se toma el ítem elegido.

Empezaremos analizando la parte de la implementación que es común en ambos casos para luego ir a los detalles que afectan el usar un control de asp.net o uno de html

 

Abrir ventana de filtro

La definición de la ventana por medio de jquery UI solo implica asociar al <div> que representara el dialog

 

$(function() {

    $('#btnOpenSupplierSearch').click(function() {

        registerGridEvent();
        
        $('#dialog').dialog('open');

    });

    $('#dialog').dialog({
        autoOpen: false,
        modal: true,
        width: 700,
        heigth: 250,
        title: 'Buscar Proveedor',
        buttons: {
            "Cancel": function() {
                $(this).dialog("close");
            }
        }
    });

});

En este caso será por medio de una acción del botón de búsqueda que se abrirá la ventana.

 

Selección sin evento (usando html <img>)

Es muy importante en este punto notar como se asocia el <img> que representa la selección de cada row del grid con su correspondiente acción en javascript.

En esta acción desde javascript no solo se toma la información del html, sino que además se cierra el dialog y se lanza el evento de búsqueda accionado el botón que tiene esta funcionalidad.

 

function registerGridEvent() {

    $('#<%=gvSuppliers.ClientID %> .imgSelection').click(function() {

        var supplierID = $(this).attr('SupplierID');

        var tr = $(this).parent().parent();
        var companyName = $('td:eq(2)', tr).text();

        //asigno datos a los controles
        $("[id*='txtId']").val(supplierID);
        $("[id*='lblSupplierName']").text(companyName);

        //cierro el popup de seleccion
        $('#dialog').dialog("close");
        
        //aplico el filtro
        $("[id*='btnFiltrar']").click();
    })

}

Re-asignación de evento jquery

Existe un punto de conflicto entre los eventos de asp.net y jquery, espacialmente cuando se usa el UpdatePanel para conservar los eventos y se mezclan acción de jquery.

Estos dos mundos no se llevan muy bien, un claro ejemplo se podría apreciar con el paginado del gridview, si bien al ir cambiando de pagina no se nota el refresco ya que el UpdatePanel lo hace simple, por debajo se genera una invocación al servidor para ejecutar del evento asociado al grid.

 

protected void gvSuppliers_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    gvSuppliers.PageIndex = e.NewPageIndex;

    LoadGridSuppliers();

    //
    // registro el evento click del boton, ya que al pagina el postback 
    // quita la asociacion del evento que jquery
    //
    string script = "registerGridEvent();";

    ScriptManager.RegisterClientScriptBlock(this, typeof(Page), "registerevent", script, true);

}

Jquery se ve afectado si es que en ese bloque se tenia eventos asociados en algún tag, en este caso concreto el tag <img> esta asociado al evento click() de jquery, por lo tanto hay que volver a re-asociar para que se revalide la acción.

Es por eso que en el evento de paginado en el server se lanza la acción en el cliente por medio del

ScriptManager.RegisterClientScriptBlock()

Esto es necesario para que a la vuelta del postback se ejecute la function javascript y asigne nuevamente el evento click() de jquery al selector definido.

 

Selección con evento (uso control asp.net ImageButton)

En este caso el camino tiene algunas vueltas entres server y cliente:

De la acción del ImageButton se ingresa al evento SelectedIndexChanged en el código .net, quien luego de tomar la información del gridview armara el script que asignara la info, cerrando el dialogo y por ultimo lanzando la acción de botón para filtrar los productos.

 

protected void gvSuppliers_SelectedIndexChanging(object sender, GridViewSelectEventArgs e)
{

    int supplierId = Convert.ToInt32(gvSuppliers.DataKeys[e.NewSelectedIndex].Value);

    string companyName = gvSuppliers.Rows[e.NewSelectedIndex].Cells[2].Text;


    string script = @"$(function(){{
                        SupplierSelected('{0}','{1}');
                    }});"; //se define {{ para poder usar el string.Format()

    script = string.Format(script, supplierId, companyName.Encode());

    ScriptManager.RegisterStartupScript(Page, typeof(Page), "popupclose", script, true);

}

 

function SupplierSelected(supplierID, companyName) {

    $("[id*='txtId']").val(supplierID);
    $("[id*='lblSupplierName']").text(companyName);

    //cierro el popup de seleccion
    $('#dialog').dialog("close");

    //aplico el filtro
    $("[id*='btnFiltrar']").click();
    
}

Un punto que no hay que pasar por alto que afecta al evento del control dentro del dialog, jquery reasigna las acciones del dialogo a nivel del body y no del form, por eso línea cambia esa acción de esta forma los eventos de asp.net se habilitan nuevamente.

 

Código
[C#]
 

36 comentarios:

  1. Buenas noches Leandro
    Perdón nuevamente por hacerte preguntas por este medio que no tienen mucho que ver con tu artículo (q por cierto igual me sirven mucho, son muy buenos) pero queeria hacerte una pregunta general: ¿eso de migrar de versión de framework depende del VS que ocupes? Por ejemplo, del framework 1.1(VS 2000) para migrar al franmework 2.0 , ¿necesitaría migrar el proyecto al VS 2005? No se si me doy a entender, pero lo que quiero saber es que el framework que utilizo para mi aplicación depende de la version del VisualStudio q utilizé para desarrollarlo? o es independiente?
    Te agradezco

    ResponderEliminar
  2. hola Georgina

    si la version del framework esta relacionado con la del VS, si usas VS2005 de seguro uses .net 2.0, pero ojo que si usas VS2008 este tiene compatibilidad para .net 2.0, 3.0 y 3.5, porque el VS permite cambiar entre estas versiones, pero el VS2005 no, este solo es .net 2.0

    para migrar a .net 2.0 exactamente necesitas pasar a VS2005

    saludos

    ResponderEliminar
  3. Hola Leandro
    Estoy realizando una aplicacion web en vb.net 2010 y me pasaron una BD en access, la cual me pide solo contraseña para ingresar.
    Mi problema reside en que no puedo establecer la conexion!!!

    Espero puedas ayudarme con algun ejemmplo... he buscado por muchas partes y todo lo que he probado no me soluciona le problema!!

    Desde ya gracias!!!

    ResponderEliminar
  4. hola nakiotio

    si revisas las opciones de connection string

    http://www.connectionstrings.com/access/

    varas que puedes definir el password y dejas de usuario admin

    saludos

    ResponderEliminar
  5. Comprendo Leandro, gracias por aclarar mi duda. Slds

    ResponderEliminar
  6. Gracias Leandro!!!!
    Ahora tengo una pequeña consulta...
    Pude establecer conexión la Base, lo que me pasa ahora es hay una tabla en particular a la cual no puedo hacer consultas... de 15 tablas que tiene la base solo esa me tirar un excepción.
    Te recuerdo que me pasaron esa base en ACCESS...

    Gracias nuevamente!!!

    ResponderEliminar
  7. hola nakiotio

    la verdad es muy poca la informacion que brindas

    dices que tienes una exception pero ni siquiera mencionas cual es el mensjae, ni en que codigo se produce, te comento que adivino aun no soy

    no seria mejor plantearlo en el foro

    Foro ADO.NET

    saludos

    ResponderEliminar
  8. Hola leandro!!!
    Tengo una pequeña duda... estoy usando VBNET y ACCESS. En la base, existe una tabla donde chequeo los usuarios, en la misma existe un campo que es PASSWORD (con mascara de entrada = contraseña, es decir, se ven en el siguiente formato *******).
    Mi problema radica en que cuando hago una consulta para verificar el correcto ingreso de la contraseña el la pag. no puedo comparar los string debido a que me trae desde la base con e lformato enmascarado!!!
    Mil gracias por consejos que das... sos un genio!!!

    Gracias...

    ResponderEliminar
  9. hola nakiotio

    la verdad esta raro el problema

    si desde el MS Access abres el archivo de la db he inspeccionas la tabla los password puede verlos ?

    si haces un select que cargue un datatable de toda la tabla si pones un breskpoint he insepeccionas el datatable en debug puede ver la info del password ?

    recuerda que para validar la autenticacion nucna recuperas el password sino que usas

    SELECT Count(*) FROM usuarios WHERE usuario = @nombre AND password = @pass

    eso si devuelve registros psa la validacion sino los devuelve no la pasa
    usas el ExecuteScalar()

    saludos

    ResponderEliminar
  10. Hola leandro, te cuento el escenario, tengo un textbox, si spreto enter, deberia mostrar una ventana modal, con una grilla que me muestre los productos, y dentro de esa misma seleccionar un determinado producto, para llenar el textbox
    Osea apreto enter y sale una ventana, selecciono un producto y se lo paso al textbox
    No se como hacerlo,m estoy desarrollando en asp.net con vs2010 y VB.net
    Muchas gracias

    ResponderEliminar
  11. podrias aplciar algo similar a lo desarrollado aqui, solo que en tu caso la accion que avre el dialogo seria con el keypress de jquery

    How to detect pressing enter on keyboard using jquery?

    en el articulo usaba el click de un boton en tu caso cambia el evento, pero el resto es igual

    saludos

    ResponderEliminar
  12. Hola Leandro, una vez te consulté sobre volver a asociar los eventos jquery luego de volver del servidor y me direccionaste a una publicación tuya.
    El problema que tengo ahora es que los eventos (click por ejemplo) de jquery se desactivan cuando, en un widget de jqueryui (datepicker), hago click en cambiar el año. Ahi se me desactivan todos los eventos que había personalizado. Pero los propios eventos del datepicker como seleccionar dia, siguen funcionando.
    Sabes de alguna forma de volver a recargar mis propios eventos?

    Muchas gracias!

    ResponderEliminar
  13. hola Leo

    la verdad es muy raro

    he usado el datepicker de jquery ui y nunca presento este problemas que describes

    estas seguro que este control el que lo causa ?

    ResponderEliminar
  14. Como andas Leandro? Sí, estoy seguro que es por ese control. los eventos de los cotroles de los plugins siguen funcionando, pero cuando hago:
    $(function () {
    $("#btnAgregar").button().click(function () {
    $("#nuevoJornada").dialog("open");
    })
    }
    por ejemplo, funciona el clic hasta que hago clic para pasar de año con el datepicker.
    Muchas gracias!

    ResponderEliminar
  15. hola Leo

    que es esto
    $("#btnAgregar").button().click(...

    eso del button() esta de mas, debria ser

    $("#btnAgregar").click(function () {

    Nota: imagino btnAgregar es un bon de html no ?


    saludos

    ResponderEliminar
  16. Como andás Leandro?
    Sí, está demás, sacando esa palabra también funciona.
    Igual sigo teniendo el problema que pierdo los eventos click y dbclick.

    ResponderEliminar
  17. hola Leo

    recuerda que si usas UpdatePanel aunque no se refresque la pagina el postback se sigue realizando

    por eso es que debes volver a rebindear los evento de jquery a la vuelve del postback del evento

    saludos

    ResponderEliminar
  18. Hola buenas noches Leandro .queria saver si puedo lograr abrir el modal con controles asp y no con un input.sera posible eso

    ResponderEliminar
  19. hola ronal

    puedes abrir el popup con el evento que necesites, podrias ser con un link, la seleccion de un combo, no tiene porque ser un boton

    saludos

    ResponderEliminar
  20. Hola Leandro.

    quiero ver la posibilidad, si puedes ayudarme, te cuento, tengo un aplicacion vb2010 y quiero cargar una segunda pagina una vez realizada la seleccion que pueda retornar el dato a la pagina anterior.

    Saludos

    ResponderEliminar
  21. hola Daniel

    pero como es que estas mostrando la pagina?
    estas usando un popup como se explica en este articulo
    o realizas un Response.Redirect() a la otra pagina para despues regresar ?

    saludos

    ResponderEliminar
  22. Leandro, gracias por responder, Voy a intentar ser más minucioso, tengo una Webform1 en la cual es un formulario, algunos campos los acompaño con unos botones de búsqueda el cual quiero que muestre otro Webform, por ejemplo, tengo un campo comuna la hacer click en el botón quiero que muestre todas las comunas acompañadas con sus ciudades, tenía en mente mostrar una Webform con una gridview, pero no sé cómo retornar el dato a campo comuna.
    Muchas Gracias.

    ResponderEliminar
  23. hola Daniel

    algo que sigue sin quedar claro es como muestras ese otro form, realizas un redirect(), usas window.open(), usas jquery UI dialog, etc

    lo planteo porque segun sea el caso la forma de retornar datos cambia

    saludos

    ResponderEliminar
  24. hola

    no analizaste el otro articulo

    [ASP.NET] PopUp Filtro – usando window.open()

    en ese muestro como usar el window.opener, para acceder al page base y pasar datos o realizar acciones

    saludos

    ResponderEliminar
  25. Hola Leandro

    Implementé esta búsqueda en un gridview:

    http://geeks.ms/blogs/gperez/archive/2011/04/10/tips-filtrar-un-gridview-con-jquery-al-presionar-una-tecla-y-no-filtra-el-pager.aspx

    Funciona bien. El problema es que cuando quiero hacer lo mismo en un panel de un popup, no funciona el evento keypress.

    Que debería modificar?



    Gracias

    Diego

    ResponderEliminar
  26. hola Diego

    se podria deverse a la forma en que armes el selector del textbox dodne asignas el keypress

    jQuery UI Dialog And The Enter – Return Key Problem

    este otro quizas no tenga mucho que ver

    Submit jQuery UI dialog on Enter

    pero veras como usan el
    $('.ui-dialog').find('button:first')

    para en este caso localizar un control dentro del dialog, quizas algo asi pero con el textbox deberias realizar

    saludos

    ResponderEliminar
  27. Buenas Leonardo!

    Se me presento el siguiente problema:
    Estoy trabajando con la api de subgurim de google maps, mi idea es la siguiente: quiero que desde un enlace impreso en el windowinfo de cada marcador que al presionar este (Historial) me arroje un popup con información detallada de ese marcador, se podrá?
    Personalizo en un string el windowsinfo del marcador y mandandolo a llamar en la clase GInfoWindow

    string infwdw = ""+ leer["SUC_ADFSA"] +
    " IP : " + leer["IP"] +
    " CPU : " + leer["cpu"] +
    "%Ultima Act. : " + leer["FECHA_ULTACT"] +
    "<.br/> Domicilio : <.br/.>" + leer["domicilio"] +
    "<.br/><.a href='Default.aspx?suc="+ leer["sucursal"] +"'>Ver Historial" +
    "<.br/><.a href='Streetview.aspx?latitud=" + leer["latitud"] + "&longitud=" + leer["longitud"] +
    "&suc=" + leer["nombre"] + "' target='_blank'>Click StreetView";

    ResponderEliminar
  28. NOTA: los puntos en cada etiqueta de HTML es para que me dejar publicar el código.

    ResponderEliminar
  29. hola Julio

    la verdad nunca trabaje con la api de subgurim y su integracion con google maps
    por lo que no sabria decirte si se puede obtener la info que planteas en el popup

    saludos

    ResponderEliminar
  30. Hola Leandro que tal soy muy nuevo en esto pero me esta llamando mucho la atención y me surgió la curiosidad de saber si se puede arrojar un popup para validar a un usuario y contraseña al momento de seleccionar un item de un combobox no se si me pudieras ayudar?

    Gracias y buenas todas tus respuestas en todos los blogs y preguntas que he visto realmente me han servido...

    ResponderEliminar
  31. hola Joaquin

    depende como implementes el login pero podrias lanzar un mensaje al usuario si lo necesitas

    podrias hacerlo con jquery, es mas podrias validar sin hacer postback a un eventos usando $.ajax, a donde apunto es dejar de usar los evento de asp.net y usar funcionalidad javascript con jquery invocando webmethods

    saludos

    ResponderEliminar
  32. Hola Leandro, buenas tardes, cual es la mejor manera de crear cuadros de dialogo con formularios, con javascript, jquery o ajax?

    ResponderEliminar
  33. hola Ana

    personalmente me gusta usar jquery UI, este se usa integra bien tanto en asp.net como en asp.net mvc

    aunque si estas mas acostumbrada a usar controles entonces el ModalpopupExtender de la toolkit seria el mas indicado

    ajax como tecnologia no se usa para crear dialogos este permite invocar el servidor sin postback de la pagina
    aunque imagino apuntabas a las ajax toolkit que son los controles

    saludos

    ResponderEliminar
  34. Saludos Leandro e intentado realizar el ejemplo que muestras, pero no lo logro, puesto que la ventana emergente me la muestra en la pagina del navegador. Es decir que en teoria desde la pagina debiese abrir una popup pero esa popup la muestra en la pagina principal. Nunca lanza la popup.... ¿qué crees que estoy haciendo mal?

    Estoy trabajando con VS 2013.

    ResponderEliminar
  35. HOla, me ayudo mucho tu articulo, pero tengo una pregunta si en el grid que esta en el PopUp agrego un campo Check en la tabla al cambiar de pagina se borra lo que selecciono, agradeceré mucho tu ayuda, gracias de antemano

    ResponderEliminar