Introducción
La finalidad del articulo es mostrar como utilizando puramente jquery se puede vincular dos dropdownlist de forma tal que al cambiar la selección de uno de ellos se recargue el contenido del siguiente.
En el articulo se hará uso de una invocación a un Page Method, para exponer la información y poder recuperar de forma dinámica.
Inicialización de las listas
En el evento Page_Load se proceder a la carga inicial de los combos, esto será útil para que el usuario visualice una selección por defecto
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { ddlPaises.DataSource = GetPaises(); ddlPaises.DataTextField = "Pais"; ddlPaises.DataValueField = "Cod"; ddlPaises.DataBind(); ddlCiudades.DataSource = GetCiudadesByPais(Convert.ToInt32(ddlPaises.SelectedValue)); ddlCiudades.DataTextField = "descripcion"; ddlCiudades.DataValueField = "cod"; ddlCiudades.DataBind(); } } [WebMethod] public static List<CiudadEntity> GetCiudadesByPais(int pais) { var query = from item in GetCiudades().AsEnumerable() where Convert.ToInt32(item["CodPais"]) == pais select new CiudadEntity { cod = Convert.ToInt32(item["Cod"]), descripcion = Convert.ToString(item["Ciudad"]) }; return query.ToList<CiudadEntity>(); }
Es importante remarcar como uno de los métodos tiene definido el atributo [WebMethod] y además se ha definido como static, este método será clave en la invocación desde el cliente con jQuery.
Cambio de selección desde el cliente, con jQuery
La definición del html es muy simple, solo son 2 DropDownList.
<form id="form1" runat="server"> <table> <tr> <td>Paises:</td> <td> <asp:DropDownList ID="ddlPaises" runat="server"> </asp:DropDownList> </td> </tr> <tr><td colspan="2"></td></tr> <tr> <td>Ciudades:</td> <td> <asp:DropDownList ID="ddlCiudades" runat="server"> </asp:DropDownList> </td> </tr> </table> </form>
La definición de script seria la siguiente:
<script language="javascript" type="text/javascript"> $().ready(function() { $("#<%=ddlPaises.ClientID%>").change(function() { // armo el objeto que servira de parametro, para ello utilizo una libreria de JSON //este parametro mapeara con el definido en el web service var params = new Object(); params.pais = $("#<%=ddlPaises.ClientID%>").val(); params = JSON.stringify(params); $.ajax({ type: "POST", url: "Default.aspx/GetCiudadesByPais", data: params, contentType: "application/json; charset=utf-8", dataType: "json", async: false, success: LoadCiudades, error: function(XMLHttpRequest, textStatus, errorThrown) { alert(textStatus + ": " + XMLHttpRequest.responseText); } }); }); $("#<%=ddlCiudades.ClientID%>").change(function() { alert("Ha seleccionado: " + $("#<%=ddlCiudades.ClientID%> :selected").text()); }); }); function LoadCiudades(result) { //quito los options que pudiera tener previamente el combo $("#<%=ddlCiudades.ClientID%>").html(""); //recorro cada item que devuelve el servicio web y lo añado como un opcion $.each(result.d, function() { $("#<%=ddlCiudades.ClientID%>").append($("<option></option>").attr("value", this.cod).text(this.descripcion)) }); } </script>
En el $().ready() se asocian a los combos dos eventos para poder atrapar un cambio de selección, es por eso que se usa el change().
Ante el cambio de selección de un país se procede en primer instancia al armado de parámetro que será enviado como filtro el Web Method, el cual se ha visto en el código anterior.
Para esta operación se hará uso de una librería de nombre json2.js, esta permitirá armar con objetos de javascript la información de una forma simple, y mediante el método JSON.stringify() convertir esta en json para ser enviada como parámetro.
En la operación también se toma el valor seleccionado en el combo usando:
$("#<%=ddlPaises.ClientID%>").val()
también se podría haber usado:
$(this).val()
ya que quien lanza el evento es el propio combo de países.
Es importante remarcar en este punto como se seleccionan los controles de asp.net usando en el selector de jquery, como asp.net renombran el atributo id de los controles es necesario usar el ClientID para tener el nombre correcto.
El siguiente paso es la invocación al método del servicio, para lo cual se utiliza el $.ajax(), hay algunas propiedades importantes que deben tenerse en cuenta, una de ellas es la definición de la url a invoca:
url: "Default.aspx/GetCiudadesByPais"
como se vera define directamente la propia pagina web donde se encuentra y luego el nombre del Web Method, pero podría ponerse los método del servicio en otro pagina si se requiere.
En el parámetro
data: params,
se define la variable del paso previo, en esta estará contenida el json que será enviado el web method.
También es importante definir si la invocación será asíncrona o no
async: true
en este caso no se espera a que el servicio web responda para continuar. Aquí no afecta si es es asíncrona o no la invocación ya que no hay código que continúe en la función javascript, pero puede que sea necesario a veces esperar una repuesta para poder tomar una decisión.
También se definen eventos en caso de una ejecución satisfactoria o un error
success: LoadCiudades,
hay varias formas de hacer esto, aquí se decidió usar una función nueva para procesar el contenido resultante de la invocación. Este método recibirá por parámetro de nombre “result” en donde se alojara el json de resultado.
Carga del combo de Ciudades
Es interesante analizar la función responsable de la carga de las ciudades proveniente de la invocación
function LoadCiudades(result) { //quito los options que pudiera tener previamente el combo $("#<%=ddlCiudades.ClientID%>").html(""); //recorro cada item que devuelve el servicio web y lo añado como un opcion $.each(result.d, function() { $("#<%=ddlCiudades.ClientID%>").append($("<option></option>").attr("value", this.cod).text(this.descripcion)) }); }
Esta recibe el resultado, y la primer operación será limpiar el combo, para ello es que lo selecciona y quita el html dentro de este, o sea quita los tag <option> que posea.
Luego toma cada valor devuelto en el json y lo recorre:
$.each(result.d, function() {..}
algo que seguro notaran extraño es el uso de result.d, este “d” es una propiedad del objeto result y allí contiene la información devuelta en la invocación, en este caso la lista de ciudades.
Se se pone un breakpoint en el código javascript, se podrá analizar claramente el valor devuelto en el json
Por supuesto el this dentro de la función representa cada ítem en el loop, y por tratarse de json este esta tipado con los mismas propiedades definida en la clase CiudadEntity devuelta por el web method.
[C#]
|
[VB.NET]
|