Aprendiendo Ext JS 3

Combos dependientes en ExtJS Más videos

Descripción del tema

En ocasiones la información que manejamos en nuestras aplicaciones está agrupada en categorías, en estas situaciones unos combos dependientes nos ayudarán a capturar estas relaciones de una manera sencilla. En el tutorial de hoy haremos dos combos que tienen relación entre sí, usaremos el típico ejemplo de mostrar los países con sus estados, la información del combo de estados será cargada con Ajax dependiendo del país seleccionado en el primer combo, te recomiendo probar la demostración para que puedas observar el resultado final.
Combos dependientes en ExtJS

Ejemplo del tutorial

Material de apoyo

Para continuar es necesario descargar el material de apoyo y copiarlo dentro de un servidor Web ya que estaremos usando Ajax para cargar la información.

La fuente de información

Vamos a escribir el código necesario para generar la información que desplegarán los combos, para este ejemplo la información estará en arreglos de PHP, pero recuerda que puede salir de una base de datos, un servicio Web (Web Service), un archivo de texto o de cualquier otro lugar.
 
$countries = array('Argentina','España','México','Perú','United States'); //step 1

$states = array( 			//step 2
	array('Buenos Aires','Córdoba','La Pampa','Mendoza','Santa Fe'),
	array('Asturias','Valencia','Barcelona','Toledo'),
	array('Distrito Federal','Nuevo León','Jalisco'),
	array('Arequipa','Puno','Tacna','Lima'),
	array('Texas','California','New york','Virginia')
);
En el paso uno se han definido los países que usaremos en el primer combo, estos son cinco países, pero pudiese ser cualquier número. En el paso dos he definido los estados de cada país, es importante mencionar que la relación se está haciendo por la posición en los arreglos, debemos tener esto en mente para escribir lo siguiente:
$id = isset($_POST['id'])?$_POST['id']:-1;	//step 1
	
if($id > -1){					//step 2
	//show states
	echo toJSON($states[$id]);		//step 3
}else{
	//show contries
	echo toJSON($countries);		//step 4
}
En el paso uno se recoge el parámetro “id”, primero verificamos que exista, si no ha sido enviado le asignamos a la variable id un “-1”. En el paso dos verificamos que el “id” sea mayor que “-1”, esto nos dice que nuestra aplicación está solicitando los estados de un país, la variable “id” debe tener la posición del país solicitado por lo tanto aquí decidimos lo que mostraremos, países o estados. El paso tres es ejecutado si la variable “id” contenía el índice del país seleccionado, por lo tanto desplegamos los estados del índice solicitado. El paso cuatro solamente se ejecuta si “id” es menor o igual a -1, esto nos dice que la aplicación ha solicitado los países. Puedes ver que se está invocando a la función “toJSON” la cual definiremos a continuación:
function toJSON($array){
	$data=array(); $i=0;			//step 1
	$total = count($array);
	foreach($array as $key=>$value){	//step 2
		array_push($data,array(
			'value'=>$i++,		//step 3
			'label'=>$value
		));
	}
	
	return json_encode(array(		//step 4
		'total'=>$total,
		'data'=>$data
	));
}
El propósito de esta función es crear el JSON que enviaremos a los combos. En el paso uno creamos dos variables, “data” e “i”, en la variable “data” iremos almacenando cada país o estado que desplegaremos en los combos, la variable “i” es muy importante ya que la usaremos para hacer la relación entre los combos, en el paso tres se explicará esto. En el paso dos creamos un ciclo que recorra todo el arreglo que recibimos como parámetro, en este arreglo se encuentra la información a desplegar en los combos. En el paso tres estamos almacenando en la variable “data” cada elemento del arreglo, puedes ver que se está creando un arreglo con dos propiedades “value” y “label”, estas propiedades serán usadas por el combo para su buen funcionamiento, a la propiedad “value” se le asigna el valor de “i”, este valor es el que enviaremos como parámetro para solicitar los estados del país seleccionado, la propiedad “label” simplemente es el texto que desplegará cada opción del combo. En el paso cuatro regresamos en formato JSON la información recolectada anteriormente.

Creación de los JsonStore

Una vez definida la información a desplegar podemos realizar los combos que usaremos, ya sabemos que los combos utilizan un Store para manipular la información que muestran. En el material de apoyo que descargaste al inicio del tutorial viene un archivo JS (linked-cmb.js) vamos a editarlo y dentro de la función “getStore” escribiremos lo siguiente:
getStore: function(){
	var store = new Ext.data.JsonStore({
		url:'linked-cmb.php',
		root:'data',
		fields: ['value','label']
	});
	return store;
}
Aquí solamente creamos un JsonStore, con los campos que definimos en el servidor, el código anterior deberíamos poder entenderlo pues lo hemos usado en varias ocasiones, lo que sí debo mencionar es que he decidido crear una función que me genere un Store porque necesito dos iguales, por lo tanto para no reescribir dos veces el mismo código, simplemente creé una función que me los genere las veces que sean necesarios.

Creación de los ComboBox dependientes

En el paso anterior creamos una función que genera un JsonStore, ahora vamos a crear dos de estos para usarlos con cada uno de los combos:
this.countryStore = this.getStore();
this.stateStore = this.getStore();
El combo que desplegará los países será de la siguiente manera:
this.countryCmb = new Ext.form.ComboBox({
	store: this.countryStore,
	id: 'country',
	valueField: 'value',
	displayField: 'label',
	triggerAction: 'all',
	emptyText: 'Select a Country',
	fieldLabel: 'Country'
});
Aquí no hay nada complicado, solamente una típica configuración de un ComboBox, lo siguiente que debemos hacer es crear el combo que va a desplegar los estados del país seleccionado.
this.stateCmb = new Ext.form.ComboBox({
	store: this.stateStore,
	disabled: true,		//Step 1
	id: 'state',
	valueField: 'value',
	displayField: 'label',
	triggerAction: 'all',
	mode: 'local',		//Step 2
	emptyText: 'Select a Contry first',
	fieldLabel: 'State'
});
Esta configuración tiene algunas diferencias con respecto a la anterior, estas diferencias son muy importantes y a continuación explico la razón: En el paso uno estamos deshabilitando el combo, de esta manera forzamos a que el usuario seleccione primero el país, este paso es opcional pero mejora la usabilidad asegurándonos que el usuario no cometa errores en la captura. El paso dos es muy importante, si no asignamos esta configuración tendremos un comportamiento extraño, ya que al asignarle “mode: 'local'” nos aseguramos que no haya peticiones Ajax al servidor cuando se expanda al desplegar sus opciones, sino que las despliegue de manera “local”.

Desplegarlos en una ventana

Hasta ahora hemos escrito código pero todavía no se ve nada en la pantalla, es hora de renderizar los componentes, para este ejemplo utilizaré una ventana de la siguiente manera:
this.window = new Ext.Window({
	title: 'Linked ComboBox',
	layout:'form',
	width:300,
	height:200,
	bodyStyle: 'padding:5px;background-color:#fff',
	items: [this.countryCmb,this.stateCmb]
});
this.window.show();
Combos dependientes en ExtJS

Creación de los ComboBox a utilizar

?

Agregando el “listener” adecuado

Hasta este punto podemos ver los combos, el combo de países despliega su información correctamente pero el combo de estados esta deshabilitado y no podemos hacer nada con él. Para poder interactuar con los componentes, necesitamos agregar un “listener” al primer combo, para que cuando éste se seleccione, habilite al combo de estados y cargue la información adecuada.
this.countryCmb.on('select',function(cmb,record,index){	//step 1
	this.stateCmb.enable();			//step 2
	this.stateCmb.clearValue();		//step 3
	this.stateStore.load({			//step 4
		params:{
			id:record.get('value')	//step 5
		}	
	});
},this);
En el paso uno le agregamos un “listener” al evento “select”, este evento se dispara cuando el usuario selecciona una opción del combo, la función recibe tres parámetros: el combo, el record y el índice que ha sido seleccionado. En el paso dos solamente habilitamos el combo de estados. En el paso tres limpiamos el valor del combo de estados, esto permitirá que si el usuario ha seleccionado anteriormente un estado, cuando se carguen nuevos estados se limpiará el valor anterior. En el paso cuatro estamos recargando la información del Store de estados con Ajax. En el paso cinco estamos enviando el parámetro “id” con el cual el servidor decidirá cuales estados regresar.
Combos dependientes en ExtJS

Combos dependientes

Conclusión

Siguiendo los pasos de esta tutorial podemos crear combos dependientes de los niveles que necesitemos, solamente necesitamos asignar un “listener” al evento “select” del combo necesario y dentro de este “listener” recargar el store del combo relacionado. No olvides seguirnos en Twitter (@quizzpot) para estar al tanto de los nuevos tutoriales que publicamos, recuerda que cada vez los temas serán más complejos; de igual manera no te olvides de dejar tus dudas o sugerencias en los comentarios.

Te gustaría recibir más tutoriales como este en tu correo?

Este tutorial pertenece al curso Aprendiendo Ext JS 3, te recomiendo revises el resto de los tutoriales ya que están en secuencia de menor a mayor complejidad.

Si deseas recibir más tutoriales como este en tu correo te recomiendo registrarte al curso, si ya eres miembro solo identifícate y registrate al curso, si no eres miembro te puedes registrar gratuitamente!

Si no gustas registrarte en este momento no es necesario! Aún así puedes recibir los nuevos tutoriales en tu correo! Jamás te enviaremos Spam y puedes cancelar tu suscripción en cualquier momento.

¿Olvidaste tu contraseña?

21Comentarios

  • Avatar-2 ShEcCiD 19/11/2009

    Hola: La verdad soy nueva en esto de ExtJs y la verdad estos tutoriales me han servido demasiado; y sobretodo por q estan demasiado explicados.. Y asi para principiantes como yo;; es mas fácil aprender... Gracias... Siempre estoy pendiente de nuevos tutoriales...

    • Avatar-5 HUIR 19/11/2009

      Muy buen Post

      • Avatar-3 Jean Hernández 14/12/2009

        Una duda, vi el tuto de carga de formularios, y acabo de ver este, en el caso en el que tenga 2 combos que se carguen desde la bd, uno sea dependiente de otro y estoy haciendo la carga del formulario via form.load(), el tratamiento es el mismo, o hay algo en lo que deba prestar atención?

        • Avatar-7 Crysfel 15/12/2009

          Recuerda que el form.load solo te carga los "values" del formulario, es decir, tu tendrías que "popular" tus combos antes de asignarle el value. Normalmente lo que yo hago es cargar el contenido del primer combo, luego le asigno su value y en ese momento traigo el contenido del segundo combo dependiendo del primero, mediante un listener le asigno el value al segundo combo. saludos

          • Avatar-2 Jean Hernández 15/12/2009

            Coloqué el tema en el foro, tengo un bug y subí el código para ver que tal, este es el tema del foro: http://foro.quizzpot.com/viewtopic.php?f=6&t=354

            • Avatar-8 Rodrigo 04/01/2010

              Hola, sabes tengo una consulta ¿como puedo hacer para desplegar 2 valores de un json store ej: 'nombre' + 'apellido' en un combo. acepto sugerencias... de antemano muchas gracias pd: soy nuevo con ext-js

              • Avatar-6 Crysfel 05/01/2010

                Lo más fácil es hacer la concatenación en el servidor, pero si no te es posible cambiar eso puedes ocupar el evento "load" del store que usa el combo, recorrer todos los registros e ir concatenando los campos que necesites en un campo "resultado" (por ejemplo). Te recomiendo darle un vistazo a la documentación del "Store" para que veas la manera de como hacer lo que te he comentado. Saludos

                • Avatar-6 Jesus A. 25/02/2010

                  Saludos a todos, Justo lo ke busco pero el PROBLEMA es que lo necesito en HTML. No se nada de PHP,He estado asociandolo a HTML pero me pierdo. Atte. Jesus A. A.

                  • Avatar-4 @zonademanel 24/04/2010

                    Muchas gracias, me sirvio un buen tu post, tenia horas y no me quedaban unos combobox dependientes

                    • Avatar-3 santiago 16/05/2010

                      tengo un problema, mi ventana no se ve, solo un pequeño rectángulo, y ya eh verificado el código y prácticamente corte y pegue, lo único que estoy haciendo diferente es que no tengo instalado un servidor entonces quiero saber si eso puede ser un error o en su defecto que podría ser, eh verificado con chrome y con ie

                      • Avatar-4 Geovanni Escalante 23/07/2010

                        Hola tengo un problema no sé porque las palabras tildadas y la ñ no me cargan en el combo, en vez de esas palabras me sale null donde puedo configurar esto porque con los demás componentes que he usado me ha salido bien las tildes y la ñ

                        • Avatar-1 Geovanni Escalante 23/07/2010

                          Al parecer el problema de las tildes y la ñ se presenta cuando traigo los datos desde php, como podría solucionar esto

                          • Avatar-9 clever 20/09/2010

                            como obtengo el dato totalProperty de un store

                            • Avatar-6 Ricardo Rios 17/11/2010

                              Hola muy interesante el tema, pero quisiera saber como lo podria realizar con varios select dependientes sacando los datos de una base de datos mysql, se como llenarlos con la data, pero no como se haria con la relación he estado intentando con unos listeners pero no me ha funcionado, aca esta lo que tengo hasta ahora. Empece con 2 para ir aprendiendo y luego seguir la cadena. Lo tengo completo en este foro: http://www.sencha.com/forum/showthread.php?116010-How-to-made-dependants-combobox-with-databases-and-JSON&highlight=combobox+.php Aqui les copio mi codigo: var paises = new Ext.data.Store({ autoLoad: true, proxy: new Ext.data.HttpProxy({ url: '../JSON/paises.php', method: 'POST' }), reader: new Ext.data.JsonReader({ root: 'dpaises' }, [ {name: 'cod'}, {name: 'pais'} ]) }); var provincias = new Ext.data.Store({ autoLoad: true, proxy: new Ext.data.HttpProxy({ url: '../JSON/provincias.php', method: 'POST' }), reader: new Ext.data.JsonReader({ root: 'dprovincias' }, [ {name: 'cod'}, {name: 'codp'}, {name: 'provincia'} ]) }); var seleccion_pais = new Ext.form.ComboBox({ store:paises, hiddenName:'pais', allowBlank:false, labelStyle: 'font-weight:bold;', triggerAction: 'all', allowBlank:false, mode:'remote', forceSelection:true, valuefield: 'cod', width:450, emptyText:'Seleccione País de la Obra...', displayField:'pais', selectOnFocus:true, minChars: '1', fieldLabel:'País', listeners:{ select:function(obj,record,index){ var dept = Ext.getCmp('seleccion_provincia'); dept.store.loadData(record.data.cod); } } }); var seleccion_provincia = new Ext.form.ComboBox({ fieldLabel:'Provincia', hiddenName:'provincia', allowBlank:false, labelStyle: 'font-weight:bold;', id:'seleccion_provincia', store: provincias, triggerAction:'all', editable:false, mode:'remote', emptyText:'Seleccione Provincia de la Obra...', selectOnFocus:true, width:450, valuefield: 'codp', displayField:'provincia', minChars: '1', fieldLabel:'Departments', });

                              • Avatar-9 Ricardo Rios 17/11/2010

                                Vean este Post: http://www.forosdelweb.com/f127/problema-con-extjs-no-funcionan-selects-dependientes-sacando-datos-bd-con-json-860585/

                                • Avatar-5 Marcela 28/03/2011

                                  Hola Crysfel quisiera saber cual es la causa para que los combos tarden demasiado en cargar, en mi caso es asi, cargan los datos correctos y todo esta bien pero tardan mucho demasiado en cargar y creo q eso ocasiono que todas las demas ventanas del sistema q estoy programando tarden en cargar excesivamente!!! hasta el login que puedo hacer??

                                  • Avatar-11 Crysfel 28/03/2011

                                    Hola @marcela He visto que cuando las pantallas se comienzan a poner muy lentas es porque se intentan desplegar miles de datos a la vez, eso hace que se inserten muchos nodos al DOM lo cual afecta considerablemente al rendimiento de la aplicación, otro aspecto a considerar es que una vez que subes a producción tu proyecto deberías comprimir tus módulos usando gzip y también el compresor de Yahoo por ejemplo. Saludos

                                    • Avatar-6 Alejandro 03/08/2012

                                      Hola, este ejemplo no funciona con internet explorer, alguien lo ha revisado?? saludos Alejandro

                                      • Avatar-3 Peter 19/10/2012

                                        y como hacer esto en ExtJS 4 a mi me carga el combo 2 cuando selecciono un valor en el combo 1, pero cuando quiero elegir otro valor del combo 1 en el combo 2 no se refrescan los nuevos valores... apoyenmeeeee!!

                                        • Avatar-6 Carlos Castaneda 16/03/2013

                                          Barbaro amigo, la mitad de lo que se de Extjs, me lo has enseñado tu... muchas gracias!!!, esto de los combos dependientes era lo que me faltaba, y me funciona genial!!!

                                          • Avatar-9 Roberto 08/04/2014

                                            Si te puedo ayudar mi correo es jesus_rguez@hotmail.com

                                            Instructor del curso

                                            Crysfel3

                                            Autor: Crysfel Villa

                                            Es ingeniero de software con más de 7 años de experiencia en desarrollo web.

                                            Descarga Código Fuente Ver Demostración

                                            Regístrate a este curso

                                            Este tutorial pertenece al curso Aprendiendo Ext JS 3, revisa todos los tutoriales que tenemos en este mismo curso ya que están en secuencia y van de lo más sencillo a lo más complicado.

                                            Tendrás acceso a descargar los videos, códigos y material adicional.

                                            Podrás resolver los ejercicios incluidos en el curso así como los Quizzes.

                                            Llevarás un registro de tu avance.