viernes, 29 de junio de 2012

[ASP.NET] PopUp Edición - Usando Jquery UI Dialog

 

Introducción


En este ejemplo se editaran ordenes de compra pero sin hacer uso alguno de eventos de asp.net, se hará uso de una serie de librerías jquery que ayudaran en el proceso

Solo el botón de filtro y la paginación del gridview conservarán los eventos de asp.net, la edición de la entidad será completamente sin hacer uso de eventos.

Para esto se usara:

  • jquery UI dialog
  • jquery autocomplete
  • jtemplates
  • momentjs

Implementando jQuery Autocomplete


La implementación se encuentra en el archivo autocomplete.js del proyecto, en este simplemente se define

$(function () {

    $("[id*='txtCustomer']").autocomplete({

        source: function (request, response) {

            var params = new Object();
            params.companyName = request.term;

            $.ajax({
                type: "POST",
                contentType: "application/json; charset=utf-8",
                url: "Default.aspx/GetCustomerList",
                data: JSON.stringify(params),
                dataType: "json",
                async: true,
                success: function (data) {

                    response($.map(data.d, function (item) {
                        return {
                            label: item
                        }
                    }))
                },
                error: function (request, status, error) {
                    alert(jQuery.parseJSON(request.responseText).Message);
                }
            });

        },

        open: function (event, ui) {

            $(this).autocomplete("widget").css({
                "width": 200, "font-size": 12
            });

        },

        select: function (event, ui) {

            $("[id*='txtCustomer']").val(ui.item.label);

        }


    });
});

 

Como puede observarse invoca a un WebMethod implementado en el código de la pagina

[WebMethod]
public static string[] GetCustomerList(string companyName)
{
    string[] list = CustomerRepository.GetCustomer(companyName)
                            .Select(x => x.CompanyName)
                            .ToArray();

     return list;
}

Es importante resaltar el uso de una sección de estilo que permite definir el scroll del desplegable

<style type="text/css">
    .ui-autocomplete {
	    max-height: 200px;
	    overflow-y: auto;
	    /* prevent horizontal scrollbar */
	    overflow-x: hidden;
	    /* add padding to account for vertical scrollbar */
	    padding-right: 20px;
    }
</style>

Implementando Edición GridView


La edición en el control GridView tiene algunos detalles interesantes para el análisis. la selección se implementa por medio de un simple template conteniendo el tag de html de imagen al cual se le asocia un atributo para identificar el id de la orden que define

Este atributo será luego usado por el evento de la imagen cuando hace $(this).attr(“idorder”)

function RegisterEditOrderEvent() {

    $("[id*='gvOrders'] [id*='imgeditorder']").click(function () {

        var orderId = $(this).attr("idorder");

        $('#popuporderedit').dialog({ title: 'Edicion Orden Nro: ' + orderId });
        $('#popuporderedit').data('orderId', orderId);
        $('#popuporderedit').dialog('open');

    });

}

Nota: hay que remarcar como se asigna el id de la orden al dialogo, usando el .data(), usado luego para saber que id esta mostrando el popup

Se observara también que este evento no esta en el clásico $(function(){… para que se cargue cuando la pagina este disponible, sino que es invocado puntualmente ante determinados eventos.

Esto es necesario porque el gridview sigue conservando los eventos de asp.net, y el postback que estos causando quitan las asociaciones de los eventos de jquery adjunta a los controles, a pesar de usar UpdatePanel estos eventos aun existen, por eso se usa al final de cada acción el ScriptManager.RegisterStartupScript() para que vuelva a lanzar la ejecución y rebindear el evento click

protected void gvOrders_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    gvOrders.PageIndex = e.NewPageIndex;
    LoadGridOrder();

    ScriptManager.RegisterStartupScript(Page, typeof(Page), "registerorderevent", "RegisterEditOrderEvent();", true);

}

protected void btnFiltrar_Click(object sender, EventArgs e)
{
    LoadGridOrder();

    ScriptManager.RegisterStartupScript(Page, typeof(Page), "registerorderevent", "RegisterEditOrderEvent();", true);
}

Edición usando jQuery UI Dialog


La definición es bastante simple, lo que quizás sea complejo es la carga y actualización de los campos de la entidad

$('#popuporderedit').dialog({
    autoOpen: false,
    modal: true,
    resizable: false,
    width: 500,
    heigth: 250,
    title: 'Edicion Orden Nro:',
    open: function (event, ui) {

        initialize();
        loadOrder($(this).data('orderId'));

    },
    close: function (event, ui) {

        //limpia todos los textbox del popup
        $('#popuporderedit :text').val('');

    },
    buttons: {
        Actualizar: function () {

            updateOrder();

        },
        Cancel: function () {
            $(this).dialog("close");
        }
    }
});

Jquery UI Dialog – Carga controles


La carga de los datos en el popup tiene dos momentos, una de inicialización y otra de asignación de los datos de la entidad que se edita

En este caso la inicialización mas que nada implica cargar los combo

function initialize() {

    loadComboBox('ddlCustomer', 'GetAllCustomer');
    loadComboBox('ddlEmployeer', 'GetAllEmploye');
    loadComboBox('ddlShipVia', 'GetAllShipper');
    
}

function loadComboBox(comboname, webmethodname) {

    var template = "{#foreach $T as record}\
                        <option value='{$T.record.id}'>{$T.record.name}</option>\
                    {#/for}";

    var combo = $('#' + comboname);

    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: "Default.aspx/" + webmethodname,
        data: '{}',
        dataType: "json",
        async: true,
        success: function (data) {

            //combo.setTemplate($("#SelectTemplate").html());
            combo.setTemplate(template);
            combo.processTemplate(JSON.parse(data.d));
           
        },
        error: function (request, status, error) {
            alert(JSON.parse(request.responseText).Message);
        }
    });

}

Es importante notar como se hace uso de jtemplate para definir el <option> de combo. El témplate puede ser definido tanto en una variable, o si este es algo mas complejo podría hacerse en una sección del html

<script type="text/html" id="SelectTemplate">
    {#foreach $T as record}
        <option value="{$T.record.id}">{$T.record.name;}</option>
    {#/for}
</script>

Para que se puede recuperar la info será necesario contar con los webmethod

[WebMethod]
public static string GetAllCustomer()
{
    var list = CustomerRepository.GetAllCustomer()
                            .Select(x => new 
                            {
                                id = x.CustomerID,
                                name = x.CompanyName
                            });

    return JsonConvert.SerializeObject(list);
}

[WebMethod]
public static string GetAllEmploye()
{
    var list = EmployeRepository.GetAllEmploye()
                            .Select(x => new
                            {
                                id = x.EmployeeID,
                                name = x.FullName
                            });

    return JsonConvert.SerializeObject(list);
}

[WebMethod]
public static string GetAllShipper()
{
    var list = ShipperRepository.GetAllShipper()
                            .Select(x => new
                            {
                                id = x.ShipperID,
                                name = x.CompanyName
                            });

    return JsonConvert.SerializeObject(list);
}

Se hace uso de la librería JSON.Net para serializar el objeto anónimo

Para cargar la orden se usa una técnica similar

function loadOrder(orderId) {

    var params = new Object();
    params.orderId = orderId;

    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: "Default.aspx/GetOrder",
        data: JSON.stringify(params),
        dataType: "json",
        async: true,
        success: function (data) {

            var order = JSON.parse(data.d);

            $('#ddlCustomer').val(order.CustomerID);
            $('#ddlEmployeer').val(order.EmployeeID);

            $('#txtOrderDate').val(order.OrderDate);
            $('#txtRequiredDate').val(order.RequiredDate);
            $('#txtShippedDate').val(order.ShippedDate);

            $('#ddlShipVia').val(order.ShipVia);
            $('#txtFreight').val(order.Freight);
            $('#txtShipName').val(order.ShipName);
            $('#txtShipAddress').val(order.ShipAddress);
            $('#txtShipCity').val(order.ShipCity);
            $('#txtShipRegion').val(order.ShipRegion);
            $('#txtShipPostalCode').val(order.ShipPostalCode);
            $('#txtShipCountry').val(order.ShipCountry);


        },
        error: function (request, status, error) {
            alert(JSON.parse(request.responseText).Message);
        }
    });


}

Definiendo el webmethod que envía los datos de la orden

[WebMethod]
public static string GetOrder(int orderId)
{
    var order = OrderRepository.GetOrderById(orderId);

    return JsonConvert.SerializeObject(new
    {
        OrderID = order.OrderID,
        CustomerID = order.CustomerID,
        EmployeeID = order.EmployeeID,

        OrderDate = order.OrderDate.ToShortDateString(),
        RequiredDate = order.RequiredDate.ToShortDateString(),
        ShippedDate = order.ShippedDate.HasValue ? order.ShippedDate.Value.ToShortDateString() : "",

        ShipVia = order.ShipVia,

        Freight = order.Freight,
        ShipName = order.ShipName,
        ShipAddress = order.ShipAddress,
        ShipCity = order.ShipCity,
        ShipRegion = order.ShipRegion,
        ShipPostalCode = order.ShipPostalCode,
        ShipCountry = order.ShipCountry
    }); 

}

Fue necesario redefinir la entidad que se envía y no directo la entidad Order ya que de no hacerse se obtiene un error de referencia circular, causado por las entidades asociadas en Entity Framework

 

Jquery UI Dialog – Actualización


Actualizar la entidad implica crear un objeto javascript que represente la entidad, lo bueno es que JSON.stringify() lo hace muy fácil, mapeando la entidad directamente

function updateOrder() {

    var order = new Object();
    order.OrderID = $('#popuporderedit').data('orderId');

    order.CustomerID = $('#ddlCustomer').val();
    order.EmployeeID = $('#ddlEmployeer').val();

    order.OrderDate = moment($('#txtOrderDate').val(), "DD/MM/YYYY").toDate();
    order.RequiredDate = moment($('#txtRequiredDate').val(), "DD/MM/YYYY").toDate();

    var shippedDate = moment($('#txtShippedDate').val(), "DD/MM/YYYY");
    order.ShippedDate = shippedDate == null ? null : shippedDate.toDate(); 

    order.ShipVia = $('#ddlShipVia').val();
    order.Freight = $('#txtFreight').val();
    order.ShipName = $('#txtShipName').val();
    order.ShipAddress = $('#txtShipAddress').val();
    order.ShipCity = $('#txtShipCity').val();
    order.ShipRegion = $('#txtShipRegion').val();
    order.ShipPostalCode = $('#txtShipPostalCode').val();
    order.ShipCountry = $('#txtShipCountry').val();

    var params = new Object();
    params.order = order;

    $.ajax({
        type: "POST",
        contentType: "application/json; charset=utf-8",
        url: "Default.aspx/ActualizarOrder",
        data: JSON.stringify(params),
        dataType: "json",
        async: true,
        success: function (data) {

            alert('Actualizacion Correcta');
            $('#popuporderedit').dialog("close");

        },
        error: function (request, status, error) {
            alert(JSON.parse(request.responseText).Message);
        }
    });


}

El único inconveniente fue con las fechas, al encontrarse en formato dd/MM/yyyy esta no era reconocida por javascript, es por eso que con ayuda de momentjs se logro cambiar de formato a una fecha correcta

 

Código


Para el ejemplo se hace uso de Visual Studio 21010, la base de datos es Sql Compract 3.5

 

[C#]
 

92 comentarios:

  1. Hola Leandro quisiera consultar sobre como podría hacer un Acortador de URL en ASP.NET web service con código visual basic o C#. como tinyurl sin utilizar ninguna clase web que realiza ello, ya que requiero para hacer en mi propio servidor.
    Si fuese posible hacer como este ejemplo que solo muestran la imagen http://sauaslp.wordpress.com/2011/11/10/customizar-rows-en-un-asp-gridview/ en todo caso un ejemplo que me pueda ayudar en ello.

    ResponderEliminar
  2. hola Kely

    la verdad nunca me plantee hacer nada parecido a lo que intetas lograr

    imagino que se podrias crearte un handler que tome algun parametro de la url y mediante alguna db saber el codigo a que url original pertence para poder realizar el redirect

    saludos

    ResponderEliminar
  3. Hola Leandro.

    He visto este ejemplo tuyo del PopUp Edición y me parece bastante interesante. He descargado el zip, pero los códigos están en C#. ¿Sería muy complicado hacerlo en VB?

    Saludos

    ResponderEliminar
  4. hola Jaume

    no seria dificil convertirlo, pero no lo hice porque en realidad la clave esta en entender el codigo jquery, y si sabes jquery(o sea javascript) su notacion es identica a c#, por lo tanto puedes interpretar este ultimo

    igualmente si quieres convertir el proyecto usa

    SharpDevelop

    con este ide open source podrias convertir el proyecto a vb.net en un solo click, lo conviertes y despues sigues con VS

    saludos

    ResponderEliminar
  5. Muy bueno el ejemplo.. aunque aun no lo analizo bien pero me salta una pregunta... es que cuando en el popup editamos y hacemos clic en actualizar seria bueno que cuando aparezca la grilla se muestres los cambios sin necesidad de apretar nuevamente la filtración, bueno estudiare el código y gracias en verdad muy bueno el ejemplo

    ResponderEliminar
  6. hola Maicol8k

    lo que planteas seria lo ideal, el tema es que localizar la row que se esta editando para trabajar con el html del grid y actualizarlo todo desde javascript, es un trabajo

    no digo que no se pueda lograr pero no sera facil, recargar el grid despues de actualizar es mucho mas directo

    saludos

    ResponderEliminar
  7. Pues es muy bueno el ejemplo pero aun no comprendo.. el codigo que esta dentro de Northwind.DataAccess
    ¿es la única manera de hacerlo?

    ResponderEliminar
  8. hola Maicol8k

    no necesariamente, es la forma que yo lo realizo y que me parece al usar ado.net es la mas optima cuando se modela con objetos

    en esta tu defines la entidad y el DataReader para cargar los datos


    saludos

    ResponderEliminar
  9. Hola Leandro, estoy trabajando con Asp.net y jquery. Mi idea es agregar una fila a una tabla que tiene nombre, apellido, fecha de alta y dos botones en la misma fila de edición y borrado.
    Intenté hacerlo con Jquery manejando $.ajax, pero, aún cuando pude agregar la fila correctamente, el código quedó muy desprolijo, porque al crear un los id y la forma de las filas las agrega dinámicamente, y me resultó muy artesanal ver cómo había armado cada td como lo había armado.
    Para mostrar los campos uso y .
    Después intenté recargar el listview, pero el $.ajax, usa [webMethod] que son estáticos, y no me permite la interacción con los controles de la página.
    Me podrías dar una idea de cómo puedo hacer?
    Muchas gracias!

    ResponderEliminar
  10. (te lo escribo de nuevo porque el anterior no salieron las etiquetas)

    Hola Leandro, estoy trabajando con Asp.net y jquery. Mi idea es agregar una fila a una tabla que tiene nombre, apellido, fecha de alta y dos botones en la misma fila de edición y borrado.
    Intenté hacerlo con Jquery manejando $.ajax, pero, aún cuando pude agregar la fila correctamente, el código quedó muy desprolijo, porque al crear un asp:ListView los id y las filas las agrega dinámicamente, y me resultó muy artesanal ver cómo había armado cada td.
    Para mostrar los campos uso asp:label y asp:button.
    Después intenté recargar el listview, pero el $.ajax, usa webMethod que son estáticos, y no me permite la interacción con los controles de la página.
    Me podrías dar una idea de cómo puedo hacer?
    Muchas gracias!

    ResponderEliminar
  11. este OrderRepository tiene que ser de tipo list?

    ResponderEliminar
  12. hola Leo

    la interaccion entre codigo javascript\jquery y controles de asp.net nunca fue buena, por lo que si logras realizar una accion con $.ajax veo dificil que despues puedas actualziar el control asp.net

    lo que si podrias hacer es despues de insertar es usar el UpdatePanel que abarque al grid y lanzar desde codigo javascript el refresh de esa seccion, asi se actualzia con la mueva info que insertaste

    Easily refresh an UpdatePanel, using JavaScript

    saludos

    ResponderEliminar
  13. hola Maicol8k

    no necesariamente, podria ser un dataset tipado

    [N-Tier] – Desarrollo en capas - Ejemplo Facturacion - parte 2

    como veras en el articulo podrias generar un repositorio usando datatable, aunque si usas clases seria mejor para definir el dominio

    saludos

    ResponderEliminar
  14. cuando se edita se llama a
    url: "Default.aspx/GetOrder",

    llama a :
    public static string GetOrder(int orderId)
    {

    var order = OrderRepository.GetOrderById(orderId);

    "ese OrderRepository" es donde me dices que puede ser un dataset tipiado

    public static class OrderRepository
    {
    public static List GetOrdersByCustomer(string companyName)
    {
    using (NorthwindContext context = new NorthwindContext())
    {
    return context.Orders.Where(x => x.Customers.CompanyName.Contains(companyName))
    .ToList();
    }
    }

    yo programo en vb.net
    si yo aria esto
    Public Shared Function GetAll() As dataset
    y aca poco toda mi consulta "Funcionaria"?

    Actualmente estoy haciendo en capas..
    capa de datos
    Public Function GetActor() As DataTable
    Dim cnx As New SqlConnection(ConexionDAO.GetCnx)
    Dim cmd As New SqlCommand
    Dim dt As New DataTable
    With cmd
    .Connection = cnx
    .CommandText = "GetActor"
    .CommandType = CommandType.StoredProcedure
    End With
    Try
    cnx.Open()
    dt.Load(cmd.ExecuteReader)
    Return dt
    Catch ex As Exception
    Throw ex
    Finally
    cnx.Close()
    End Try
    End Function
    capa logica
    Public Function GetActor() As DataTable
    Return ActorDAO.GetActor
    End Function
    mi codigo de la capa presentacion

    aca es donde tendria el claro cambiando el lengua a vb.net
    public static string GetOrder(int orderId)
    {
    entonces aca yo pondria mi datasetipida.getorderbyid(orderid)
    var order = OrderRepository.GetOrderById(orderId);
    osea siempre uitlizaria un repositorio... que tenga la estructura??? "lo que acabo de mostrar es para que me guies. un saludo espero tu respuesta.. aca en Peru 1 am Saludos"

    ResponderEliminar
  15. hola Maicol8k

    si vas a trabajar con funcionalidad que se comunica por ajax entocnes no puede usar un datatable, porque requieres algo tipado que se pueda serializar

    salvo que el repositorio retorne un datatable y justo antes de devolver el valor como respuesta del webmethod (el que se invoca con $.ajax) alli lo conviertas a una clase que se pueda serializar json

    saludos

    ResponderEliminar
  16. Muchas gracias Leandro! Lo pruebo y te comento como me fue.
    Saludos!

    ResponderEliminar
  17. Listo! funcionó! el único problema es que se carga toda la página completa y no se actualiza sólo el updatePanel.
    Quizás el funcionamiento normal de ejecutar el __doPostBack('updPanelUsuario_Load', ''); recarga siempre toda la página?
    En asp:ScriptManager pongo EnablePartialRendering="true", pero tampoco lo soluciona.

    Muchas gracias Leandro!
    Saludos

    ResponderEliminar
  18. hola Leo

    pero el UpdatePanel solo abarca una seccion reducida de la pagina ?
    o sea no es que el updatepanel esta abarcando todo la pagina porque entonces si recargaria todo


    saludos

    ResponderEliminar
  19. Hola Leandro, si, me llama la atención que sólo abarca una sección reducida de la página el updatePanel (una tabla hecha con asp:Listview), pero igualmente vuelve a cargar la página completa. algo estaré haciendo mal entonces?

    Te agradezco mucho por ayudarme!
    Saludos

    ResponderEliminar
  20. solo para probar porque no pones un boton dentro del updatepanel y desde el _doPostBack lanzas el evento del mismo para ver si sucede lo mismo

    puede que al indicarle solo el nombre del updatepanel no lo este tomando y lo inteprete de forma global

    lanzar la accion de un control concreto podria validar si es correcto el camino

    saludos

    ResponderEliminar
  21. Si perfecto! era eso! Ahora te molesto con la última consulta. No me acordaba que me pasaba hasta que hice funcionar el update panel(ir y venir al servidor con asp.net). Todos los eventos y efectos jquery me desaparecen después de volver de un UpdatePanel, ya no funcionan los popups, los botones que estaban creados con jquery desaparecen, etc.

    Tuviste este problema alguna vez? en su momento yo lo había solucionado poniendo "Sys.WebForms.PageRequestManager.getInstance().add_pageLoaded(nombre_de_la_funcion);" al principio de la página para que me vuelva a cargar los elementos que quería, pero me parece mas un parche que otra cosa.

    Espero me puedas ayudar con esto último! muchas gracias Leandro!
    Saludos

    ResponderEliminar
  22. si es problam es muy comun en un ambiente asp.net con jquery

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

    en el titulo "Re-asignación de evento jquery"

    saludos

    ResponderEliminar
  23. Muchas gracias por tu ayuda Leandro!

    Saludos!

    ResponderEliminar
  24. Hola Leandro, disculpá que te moleste de nuevo, pero estoy hace varias horas con esto y no puedo resolverlo.
    Serialicé un objeto en Asp.Net con JSON que ví que usas en algunos post, y la verdad me resultó de mucho utilidad, pero por ejemplo, al querer la propiedad days de un elemento TimeSpan dentro de mi objeto, no me lo reconoce desde jquery. Será que hasta ese nivel no serializa?
    Después usé otra de las librerias que vi que usabas, jmoment.js para procesar fechas desde Jquery. El problema es que procesando el formato 1.03:40:00 de muchas formas, en el unico caso que lo puedo obtener de forma correcta es cuando está ese cambio de día 1.03:40:00. Lo obtengo con moment(hora, "D.HH:MM").date(), pero aquellas horas que no tengan dia siguiente, cuando pongo moment(hora, "D.HH:MM").date() aparece el valor de la hora correspondiente, pero eso no me sirve, porque en caso que la hora sea 01:33 voy a confundir el 1 de la hora con el 1 del día. Espero haber sido claro. Respecto a la serializacion desde Asp.Net se me ocurrio enviar desde alli el valor de día además del objeto que envío, pero no sé como hacer porque actualmente tengo return JsonConvert.SerializeObject(j); siendo j el objeto que contiene en algunos de sus parametros tipo de datos Timespan.

    Espero haber sido claro!

    Saludos!

    ResponderEliminar
  25. hola Leo

    las fechas y horas son todo un problema en json y javascript

    lo que podrias hacer es no enviar un DateTime o TimeSpan como serializacion del objeto json, sino que define algo directo con formato, si tienes un timespan dale formato a string para devolverlo

    si usas json.net (en el codigo .net) podrias serializar objetos anonimos

    la idea es que devuelvas

    proptimespan.ToString("HH:mm")

    o sea que sea string con formato

    saludos

    ResponderEliminar
  26. Leandro! Ya lo resolví! puedo enviar un array de objetos serializados desde el WebMethod! Gracias Igual!
    Saludos

    ResponderEliminar
  27. Justo me contestaste! voy a probar tu solución también!
    Muchas gracias!!

    ResponderEliminar
  28. Hola Leonardo mi pregunta es la siguiente

    estoy utilizando mi programa por capas no manejo en estas linq, la manera que tengo para consultar es por medio de DataSet y en tu ejemplo utilizar List me podrias por favor explicar la forma de convertir los metodos de WebMethod para que funcione en mi codigo : yo lo intente de esta forma en uno de los metodos:

    [WebMethod]
    public static DataSet GetCustomerList(string companyName)
    {



    cEClientes oEP = new cEClientes();

    cR_Cliente oRP = new cR_Cliente();
    oEP.Id = companyName;
    DataSet oDs = new DataSet();
    oDs = oRP.Consultar(oEP);





    return oDs;


    }//fin metodo



    Agradeceria cualquier sugerencia y ayuda muchas gracias

    ResponderEliminar
  29. hola Alex

    los webmethods para hacerlos trabajar en un entorno web no funcionan con dataset, porque recuerda que tienen que serializar a json y el dataset no es compatible

    quizas debas convertir los dataset en entidades con clases y listas antes de retornar el resultado del webmethod

    saludos

    ResponderEliminar
  30. hola Leonardo

    podrias colocar por favor un ejemplo de como convertir los dataset en listas muchas gracias

    ResponderEliminar
  31. hola Alex

    podrias recorrer las filas del datatable he in volcando esto a una lista

    List list = new List();

    foreach(DataRow row in dt.Rows){
    nombreclass item = new nombreclass();

    item.prop1 = row["campo1"].ToString();
    item.prop2 = row["campo2"].ToString();

    list.Add(item);

    }

    con eso tendrias la lsita cargada en base al datatable
    saludos

    ResponderEliminar
  32. muchas gracias leonardo probare el codigo y te comento como me fue

    ResponderEliminar
  33. Hola Leandro volví a hacer tu ejemplo pero en VB y así de manera general me quedaron dos dudas:
    1.¿por qué incluyes el archivo JSONExtension.js ? pregunto porque sin incluirlo el ejemplo funciona muy bien o es que podría surgir algún problema??(Noté que tampoco lo mencionas en tu articulo a diferencia de los otros archivos .js)
    2.De esta pagina que es de donde obtuviste el archivo json2.js :http://www.json.org/ me podrías indicar exactamente cual de todas esas descargas es la que usaste (pregunto porque quisiera saber si hay actualizaciones disponibles como el caso de jquery o jqueryUI o los otros js que usaste).
    Espero que me puedas contestar y desde ya gracias.
    Hasta luego.

    ResponderEliminar
  34. Leandro, Muy buen post. quiero consultarte sobre lo siguiente:
    estoy tratando de implementar lo de este post para una pequeña aplicacion que estoy haciendo, ya lo tengo todo, pero no me funciona cuando le doy clic al icono de edicion (la imagen) no abre el dialog, podrias decirme en que parte se le agrega el evento click?.

    Gracias!

    ResponderEliminar
  35. hola Edalo

    - si tienes razon el JSONExtension.js no hace falta que este, lo que sucedio es que en un momento se presento problemas con los tipos de datos datetime y esa libreria parecia resolverlos, pero resulto que no del todo, despues di con moment.js y esa si resolvio el problema pero olvide quitar la anterior

    - en realidad no te preocupes por json2 porque ni siquiera lo necesitas, la funcionalidad de parse y stringify son parte del propio javascript

    JSON (Objeto de JavaScript)

    saludos

    ResponderEliminar
  36. hola SaulH

    al funcionalidad del click se agrego cuando se hace

    $("[id*='gvOrders'] [id*='imgeditorder']").click(function () {

    alli es cuando se asigna el evento click de jquery

    se filtra por el nombre del grid y dentro de este a todos las imagenes

    saludos

    ResponderEliminar
  37. Leandro muy agradecido con tus aportes, me sirve de mucho para mi aprendizaje

    ResponderEliminar
  38. Por mucho que lo intento no consigo que funcione mi traduccion de este codigo con vb y he leido que Edalo lo ha conseguido. Seria posible que me lo pasaras?

    ResponderEliminar
  39. hola

    cual es la parte que no notas no funciona?

    porque el codigo es bastante mas javascript que .net

    saludos

    ResponderEliminar
  40. Perdona que conteste tan tarde. El problema es que no entiendo mucho javascript. No se por donde empezar. Lo que yo quiero es que cuando pulso sobre el registro del grid me abra una ventana y me deje modificar los datos. Todo ello si puede ser en VB que lo entiendo mejor. Solo necestito los pasos para empezar.
    Un saludo.

    ResponderEliminar
  41. hola Jaume

    si vas a usar la tecnica que describo en el articulo en vb.net solo no se podra realziar, vas a necesitas bastante de javascript

    para convertir el codigo c# podrias usar
    http://converter.telerik.com/

    aunque tambien podrias usar los controles de ajax toolkit

    [ASP.NET] PopUp Edición - Usando Ajax Toolkit ModalPopuExtender

    con este podrias evitar bastante codigo cliente, quizas sea algo mas simple

    saludos

    ResponderEliminar
  42. Hola Leandro,me he descardo la aplicacion ya que quiero estudiarla,pero al momento de ejecutarla y presionar el boton filtrar da este error en el code del archivo NorthwindRepository.cs : No se encuentra el proveedor de datos .NET Framework solicitado. Puede que no esté instalado.

    Como proveedro de datos tengo el sqlCompact 3.5 y el 4.0 no he tocado nada en el web.config,a que se debe ese error si no fuera mucha molestia.
    Gracias

    ResponderEliminar
  43. Estimado,

    quisiera saber porque cuando trato de realizar la rutina para llenar un combo o select me arroja el siguiente error:
    Uncaught TypeError: Object [object Object] has no method 'setTemplate'

    control.setTemplete(template);


    Observación:
    Tengo este select dentro del un control ASP.NET

    ResponderEliminar
  44. hola LEOFREDES

    has validado que el .js de la libreria de Template este referenciada de forma correcta

    sino reconoce la funcionalidad es porque el .js no esta correctamente referenciado, valida que el , este bien definiro en el path relativo

    saludos

    ResponderEliminar
  45. Me encanta tu blog siempre me ayuda mucho!!!! :)

    ResponderEliminar
  46. Me encanta tu Blog!! Siempre me sacan de dudas :)

    ResponderEliminar
  47. Leandro, he descargado el proyecto. lo estoy corriendo en vs2012, pero me esta presentando el siguiente error "Unable to find the requested .Net Framework Data Provider. It may not be installed." en GetCustomer.

    Me parece que me falta instalar un componente.. muchas gracias de antemano

    ResponderEliminar
  48. hola Justo Castillo

    el tema es que seguramente el VS2012 tenga soporte para Sql Compact 4 y le falte el de 3.5

    es por eso que menciona la falta del proveedor

    saludos

    ResponderEliminar
  49. Buenas tardes,

    Tengo un control de usuario (.acsx) el cual es un formulario con un textbox, un dropdownlist, un fileupload y un botón para enviar en un correo esos datos, ese control de usuario lo cargo en un popup de jQuery, pero no logro al hacer clic en el botón capturar los valores que tienen esos controles. Qué puede suceder al respecto. Agradezco cualquier ayuda al respecto.

    ResponderEliminar
  50. hola Holmand

    dentro de div que forma el popup de jquery seguro este este user control

    ahora bien lo defines dentro de un updatePanel ? lo planteo porque sino causara un postback de toda la pagina

    en cambio dentro de un upadatepanel solo esa seccion es la que se actualiza

    saludos

    ResponderEliminar
  51. hola leandro gracias por tus aportes, son de gran ayuda. Mira, no se como generar las clases NorthwindContext.cs y NorthwindRepository.cs, estaba investigando y me dicen q se hace con entity framework o code first, pero no entiendo mucho no se si prodrias explicar al menos un poco par, con el resto de codigo o sea jquery si conozco no tengo ningun problema. Por favor, podrias explicarme...

    ResponderEliminar
  52. hola Hugo

    exacto se realiza con Entity Framework Code First

    Get Started with Entity Framework (EF)

    justo estaba armando unos articulos sobre el tema de EF, calculo esta seman los tendre terminados para publicarlos

    saludos

    ResponderEliminar
  53. Hola Leandro Tuttini!! Muy bueno el tutorial. mi pregunta es Si eso se puede hacer en visual Studio 2008?

    ResponderEliminar
  54. hola Abel

    claro que se puede, quizas se complique la creacion del menu con los tab

    pero el resto de editar en una ventana seguro que se puede, ya que alli se usa jquery y este no tiene ningun tipo de limitacion con el VS2008

    saludos

    ResponderEliminar
  55. Gracias !!! , Lo estoy intentando pero No se como implementarlo!!! ya que me bota error en todo.

    Podrías hacer un tutorial, pero en VS 2008? , estaría agradecido, así como muchos los estarían. Gracias por el aporte.

    ResponderEliminar
  56. hola Abel

    pero no tomes el codigo de este ejemplo y lo implementes a ciergas

    trata de entender la idea y llevar la parte que necesitas a tu codigo

    me parece raro que de error en todo, ya que mucho del codigo es codigo cliente, por lo que no puede fallar en la compilacion con muchos errores, quizas al ejecutar, pero deberias ser mas rpeciso con que error estas obteniendo, recuerda validar que los archivos .js se referencian correctamente en la pagina

    saludos

    ResponderEliminar
  57. por favor me pudieses enviar un ejemplo como guardar un NUEVO datos desde un modal similar al ejemplo que publicaste ,i correo es utp-jafs@hotmail.com

    ResponderEliminar
  58. Hola leandro, mucho gusto, recurro a usted ya que ha resuelto un sin fin de dudas respecto en codigo.
    tengo lo siguiente:

    tengo un formulario con un datagrid, un textbox el cual me genera una busqueda predictiva con jquery.

    mi problema es: como le hago para habilitar un botton cuando no tengo ningun dato en el datagrid?

    pd; el botton de entrada esta inhabilitado, cuando se busca un nombre y el grid queda vacio, el botton debe de habilitarse.

    Gracias por tu tiempo..!

    ResponderEliminar
  59. hola juan alex

    pero no hay mucho de diferente, si lograste entender la tecnica que aqui se explica

    crear un item nuevo solo es mostrar un popup con los campos vacios y definir el boton que diga "Crear", lo cual enviara los datos usando json y realizara el INSERT, eso es todo

    saludos

    ResponderEliminar
  60. hola amc_sv

    cuando dices "busqueda con jquery" es que utilizas $.ajax, $.getJSON, etc para lanzar una busqueda al servidor ?

    o sea la idea es que ante la respuesta de esta busqueda habilitar un boton o sea usar

    $('#button1').removeAttr('disabled');

    porque imagino el boton ya tenia el atributo disabled definido

    saludos

    ResponderEliminar
  61. Hola leandro, no hago la busqueda al servidor, la hago directamente con el cliente y solo utilizo Jquery y mi codigo es el siguiente,

    $("#<% = txtBuscarReg.ClientID %>").keyup(function () {
    var s = $(this).val().toLowerCase().split(" ");
    $(".filtrar tr:hidden").show();
    $("#btnNuevo").dblclick(function () {

    });
    $.each(s, function () {
    $(".filtrar tr:visible .indexColumn:not(:contains('"
    + this + "'))").parent().hide();



    utilize lo siguiente pero no me sirvio de mucho

    var conteo = $('[id$=GridView1] tr').length -1;

    document.getElementById('<%=GridView1.ClientID %>').length -1;



    if (conteo === 0) {

    $('[id$=btnPrueba]').attr('disabled', true);

    } else {

    $('[id$=btnPrueba]').removeAttr('disabled', false);

    }

    como vez lo hago contando lo que se ve en el gridview, por cierto con tu comentario de si utilizo Ajax directamente con el servidor, tratare de buscarlo ya que me diste una idea de hacerlo con el servidor directamente.


    ya que a como lo quiero hacer con el cliente no me sale =(

    gracias por tu tiempo..!

    ResponderEliminar
  62. hola

    pero porque te complicas si hay plugin de jquery que hacen esto muy simple

    [ASP.NET] Plugin jQuery quickSearch: Filtrar tablas y listasz

    saludos

    ResponderEliminar
  63. Hola Leandro, al momento hice una aplicación web con c#, donde utilizo el jQuery ui dialog, y todo el funcionamiento con jQuery, pero al momento de realizar el postback para guardar los datos, no hace el postback. Aqui la parte del dialog
    $("#dialog-form").dialog({
    autoOpen: false, height: 680,width: 490,
    bgiframe: true, modal: true,
    show: {effect: "blind",
    duration: 700},
    hide: {effect: "explode", duration: 700},buttons: {
    Aceptar: function () {var btnAdd = $get("%=btnIngresar.ClientID%>"); __doPostBack(btnAdd.name, 'click');}); por favor tu ayuda.

    ResponderEliminar
  64. hola Dany

    es que si usas un popup de jquery no deberias realizar ningun postback, deberias trabajar con ajax

    como habras visto en este articulo no realizo ningun postback a un evento sino que uso el $.ajax para realizar la accion en el servidor

    el popup de por si modifica un simple div para hacerlo popup, esto hace que quizas las funciones de javascript de asp.net no esten habilitadas, peor mas alla de eso no recomendaria usar el _doPostBack() con una ventana popup de jquery

    saludos

    ResponderEliminar
  65. Muchas gracias por tu tiempo y ayuda Leandro, pero tambien quería comentarte que el inconveniente ocurre, cuando se selecciona en el menú de la master otro formulario, y pareciera que la llamada que se da a cualquier menú se pierde, por eso tambien es mi duda.

    O al momento de implementar Ajax en toda la forma de la llamada al DIV esto ya no debería ocurrir.

    Quedo en espera de tus comentarios.
    Saludos.

    ResponderEliminar
  66. hola Dany

    no entendi la relacion entre una ventana de popup y el menu

    el menu seguramente tenga un link que realiza un postback para cargar la pagina, es logico que perderas el popup si es que desde el menu navegas a otro sitio

    saludos

    ResponderEliminar
  67. Hola Leandro, muchas gracias por tu ayuda, te comento que ya pude solucionar el problema.

    Lo que pasaba es que en el momento que obtenia los datos con código asp.net, este control deshabilitaba el postback de la página, ya que parece que no es compatible con .net, entonces al obtener los datos con ajax, funcionó correctamente.

    Entonces este control debe utilizarse con javascript o Ajax(json - ws), y funcionará muy bien.

    ResponderEliminar
  68. Que tal Leandro, primero que nada, un gusto saludarte.

    Fíjate que el enlace para bajar el codigo está roto, ¿lo puedes por favor volver a subir?

    Muchas gracias como siempre.

    Saludos desde México.

    ResponderEliminar
  69. hola Alan

    acabo de ingresar al link y lo realice sin problemas

    es un link de skydrive, puedes acceder a este desde la red donde te encuantras? lo pregunto porque hay empresas que lo bloquean

    saludos

    ResponderEliminar
  70. Doc excelente publicacion, pero como puedo insertarle una coneccion asi

    ResponderEliminar
  71. hola Boris

    no entendi, como es eso de insertar una conexion?

    apuntas a definir el connection string? porque eso lo declaras en el web.config, alli indicas a que db se conecta

    saludos

    ResponderEliminar
  72. hola Leandor me encuentro en un problema y se que solo tu podras ayudarme soy nueva en jon.. y stoy haciendo un proyecto q abre un xls d dond obtiene datos esos datos los convierto en json el problema que no se como mostrarlo en un una tabla en c# asp.net

    ResponderEliminar
  73. hola Mariuxi

    como estas invocando la funcionalidad que devuelve json ? usas una llamada ajax a un webmethod

    lo pregunto porque esa tabla podria ser de jqGrid, se integra muy bien con ajax


    saludos

    ResponderEliminar
  74. Buenas leandro tengo una consulta si modifico $('label1').html('nuevo texto'); con la respuesta del web method como le hago saber al servidor que ese valor a cambiado? , porque no actualiza siempre.

    ResponderEliminar
  75. Leandro , Como puedo mantener en una pestaña en particular un valor para esa pestaña si hago un reenvio desde el navegador?, he probado con el ViewState pero no se puede, o en dado caso darme cuente que es un reenvio y no dejar que ejecute la ultima accion, gracias de antemano.

    ResponderEliminar
  76. hola Freddy

    no puedes informar al servidor salvo que despues de modificar realices una invocacion ajax con jquery usando el $.ajax he invocando un webmethod

    saludos

    ResponderEliminar
  77. hola Freddy

    imagino esto se relaciona a mentener el valor del label, no?
    si es asi ademas de poner el valor en el label deberias ponerlo en un hidden de asp.net, de esta frma el valor viajara en el postback al servidor para poder trabjarlo, luego cuando vuelve al cliente la respuesta tomarias el valor del hidden y lo asignarias al label

    pero algo que no me queda claro es porque pierdes el valor del label, porque si usas un control Label de asp.net este conserva el valor por si mismo

    saludos

    ResponderEliminar
  78. Hola Leandro,

    Necesito de tu ayuda, me encontre con el siguiente problema, al procesar series de tiempo (archivos excel que genera un sensor de temperatura), lo que hago es:
    1. cargar el archivo excel con fileupload y mostrar los datos en un gridview.
    2. Migrar lo que esta en el gridview a SQL Server, y aqui me encontre con que las fechas del excel son de este tipo (07/27/10 00:30:00) el año solo tiene 2 digitos
    2.1. Recorro el gridview y debo ir guardando en una lista los datos para ir insertandolos a las tablas en SQL.
    Pero mi problema es que no puedo capturar la fecha del gridview hacia un objeto DateTime.
    He probado de estas formas y ninguna me funciona:
    a) FechaHora = Convert.ToDateTime(fila.Cells[1].Text)
    b) FechaHora = DateTime.Parse(fila.Cells[1].Text.ToString())
    c) FechaHora = Convert.ToDateTime(fila.Cells[1].Text.ToString())

    y el error que muestra es "No se puede reconocer la cadena como valor DateTime válido."

    Supongo que debe ser porque el año tiene 2 dígitos y no encuentro como cambiarlo a 4 dígitos.

    Tienes alguna idea de como debo tratar esta fecha? (07/27/10 00:30:00)

    Espero puedas ayudarme, gracias.

    ResponderEliminar
  79. Hola Leandro quiero hacerte una consulta: Resulta que tengo un proyecto en ASP.Net en el cual un usuario administrador debe registrar un formulario con N cantidad de preguntas las cuales se almacenan en una DB SQL. luego otro tipo de usuario deberá contestar todas las preguntas registradas anteriormente. lo que necesito saber es como hacer para cargar en una pagina todas estas preguntas y dejar el espacio para que el usuario responda.. hasta ahora lo único que se me ocurre es mandar una consulta sql que me traiga todas las preguntas registradas y luego de acuerdo a la cantidad de registros que regrese la consulta, cargar en tiempo de ejecucion la misma cantidad de textbox para cargar en ellos las preguntas y también la misma cantidad de controles para las respuestas a esas preguntas, ya sean combobox o textbox, etc... hasta ahora solamente he programado aplicaciones de escritorio en C# y creo que se podría hacer de esa forma, pero no se si en ASP.Net podría hacerse de la misma manera o que me recomiendas tu que haga?? espero haberme explicado bien :) Saludos

    ResponderEliminar
  80. hola Luis

    no evaluaste usar un control Repeater o ListView?
    en estos controles puede definir un template y asignar un DataSource para crear N cantidad de items

    en tu caso asignarias una List<> de preguntas, si puedes define una clase y usa listas genericas, cada control del template lo asignas a una propiedad, dejando uno sin vincular, ese sera el campo de respuesta

    saludos

    ResponderEliminar
  81. Hola Leandro, una duda para llamar un metodo de codebehind desde jquery, se usa el [WebMethod]?

    ResponderEliminar
  82. hola Ana

    exacto, puedes definir un webmethod en la propia pagina aspx
    y usar jquery con el $.ajax() para invocarlo

    saludos

    ResponderEliminar
  83. Hola Leandro, cree un método desde el codebehind colocando el Webmethod, yo estoy trabajando con vb.net, pero al invocar mi método desde el jquery lo hago de la siguiente manera:

    function validacion() {
    $.ajax({
    type: "GET",
    url: "HojaControl.aspx/numReplicarMsj",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data){
    alert("Realizado correctamente " + data.numReplicarMsjResult);
    },
    error: function (request, status, error) {
    alert(error);
    }
    }
    );}

    Pero solo me dice que hay un error interno, lo que hice fue quitarle el contettype y datatype pero me dice que es exitoso, sin embargo no entra al método que invoco, pero al pageload si entra.

    ResponderEliminar
  84. hola Ana

    cambia el type a POST
    ademas al webmethod lo defines como static ? porque es importante

    si pones un breakpoint en el codigo .net el webmethod se detiene ? porque sino lo hace entonces no esta llegando la invocacion

    saludos

    ResponderEliminar
  85. Hola Leandro,

    justo lo que necesito pero surgieron un par de preguntas.

    Mis preguntas son:

    1. De qué manera me recomiendas mandar llamar al modal?, ya que tu lo tienes dentro del mismo "Default.aspx" en un div y la forma en la que yo lo hago es por medio de un script que abre "MiPagina.aspx".

    2. Si es por medio de mi método, cómo le puedo aplicar formato (CSS) al modal, más no a "MiPagina.aspx"

    de antemano, muchas gracias.

    ResponderEliminar
  86. Leandro,

    quiero ver tu ejemplo y no funciona, al momento de ejecutarlo solo sale el header con el título EDITAR ORDEN DE COMPRA, la pestaña HOME, un label con Nombre Compañía y su textbox, con un botón FILTRAR.

    Le doy click a FILTRAR y no sucede nada, trato de escribir en el textbox y me aparece que no se encuentra el proveedor de datos .NET Framework solicitado. Puede que no esté instalado.


    Por qué no funciona tu aplicación cómo en la descripción?

    nuevamente, gracias!.

    Saludos

    ResponderEliminar
  87. hola Aaron

    pero para filtrar primero tiene que resolver el autocomplete

    si el autocomplete no define un item valido el boton de filtro seguro no encuentre que mostrar en el grid

    saludos

    ResponderEliminar
  88. hola Aaron

    si lo que tienes es una pagina aspx lo que quieres mostrar en un popup lo uncio que se me ocurre es usar el window.open() de javascript poniendo la url a esa pagina

    o quizas usar el modalpopupextender si dentro defines un iframe

    no se como se comportara jquery con un iframe, no creo que le guste mucho, no creo que jquery sea el indicado si vas a cargar paginas

    saludos

    ResponderEliminar
  89. He migrado un sistemas de 2003 a 2012 en asp.net pero me da el siguiente error


    0x800a1391 - Error en tiempo de ejecución de JavaScript: 'RadUploadNameSpace' no está definido

    y en mi pagina inicio.aspx me arroja este codgio en linea

    window['RadProgressManager'] = new RadUploadNameSpace.RadProgressManager([
    500, 'Telerik.RadUploadProgressHandler.aspx', 'rU_RId', 'b55fa1bf-b53a-44d3-8768-1cc10026a9c6', '', '', 'Form1', true, false
    ]);</scr

    pero cuando lo quiero modificar poara cerrar no me deja, si tienes algo para poder ayudarme te lo agradeceria mucho

    Attentamente

    Robert Jimenez Paucar

    ResponderEliminar
  90. Hola leandro, podrias ayudarme con la validación de los campos en el popup, trate de hacerlo con el jquery.validate pero no funciono.

    Gracias, saludos

    ResponderEliminar
    Respuestas
    1. hola
      Jquery validate aplica del lado del cliente, no veo porque no deberia funcionar
      quizas debas plantear el problema en el foro de asp.net
      ya que alli podrias poner codigo de como intenaste aplicar las validaciones.
      Verificaste si tienes algun error de javascript desde el Developer tools del browser?
      saludos

      Eliminar