En esta entrada vamos a explicar como asociar dos selects mediante ajax y al modificar el elemento seleccionado en uno de ellos cambie el contenido del otro.
Podemos ver el ejemplo de funcionamiento aquí.
Un ejemplo muy claro para esta situación sería dos selects, uno con provincias y el otro con localidades, lo que queremos es que al cambiar de provincia varíe la lista de localidades y muestre las que están en la provincia seleccionada.
Lo haremos utilizando el ajaxHelper, para que no sea necesario la recarga de la página y quede más atractivo.
Lo primero que haremos será definir los modelos de provincias ,localidades y un tercer modelo en el que usaremos los selects, por ejemplo podría ser un modelo de cliente, en el que al insertar un nuevo cliente tendríamos que elegir la provincia y localidad a la que pertenece.
Modelos
Modelo de provincia.
/app/models/provincia.php class Provincia extends AppModel { var $name = 'Provincia'; }Modelo de localidad.
/app/models/localidade.php class Localidade extends AppModel { var $name = 'localidade'; }Modelo de cliente.
/app/models/cliente.php class Cliente extends AppModel { var $name = 'Cliente'; }Controladores
Después de esto tendremos que definir los controladores.
Controlador de localidad.
/app/controllers/localidades_controller.php class LocalidadesController extends AppController { var $name = 'Localidades'; }Controlador de provincia.
/app/controllers/provincias_controller.php class ProvinciasController extends AppController { var $name = 'Provincias'; }Y por últino el controlador de clientes que será el que implementará la funcionalidad.
Controlador de cliente.
/app/controllers/clientes_controller.php class ClientesController extends AppController { var $name = 'Clientes'; var $helpers = array('Ajax'); var $uses = array('Cliente','Provincia','Localidade'); function insertar() { $listadoProvincias = $this->Provincia->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC')); $this->set('provincias', Set::combine($listadoProvincias, "{n}.Provincia.id","{n}.Provincia.nombre")); $primera_provincia = $this->Provincia->find(null,null,'nombre ASC'); $listadoLocalidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC','conditions'=>'Localidade.provincia_id='.$primera_provincia['Provincia']['id'])); $this->set('localidades', Set::combine($listadoLocalidades, "{n}.Localidade.id","{n}.Localidade.nombre")); // RESTO DE LA FUNCIONALIDAD DE INSERCIÓN DE CLIENTES } function update_select() { if (!empty($this->data['Localidade']['provincia_id'])) { $provincia_id = $this->data['Localidade']['provincia_id']; $localidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC','conditions'=>array('provincia_id'=>$provincia_id))); } else { $localidades = $this->Localidade->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC')); } $this->set('options', Set::combine($localidades, "{n}.Localidade.id","{n}.Localidade.nombre")); $this->render('/elements/update_select', 'ajax'); } }Por un lado tenemos la función insertar, que será una función genérica de inserción de clientes. La parte que a nosotros nos interesa es en la que se inicializan las variables que después utilizaremos en los selects, estas deberán ser arrays en los que cada elemento tenda un identificador y su valor, para que el select pueda utilizarlos en la vista.
En la versión 1.1 de cakephp, esto se podía hacer mediante la función generateList del modelo, función que se ha eliminado en la 1.2.
Por ello ahora es necesario hacerlo en dos pasos, por un lado realizar la búsqueda con un findAll y después utilizar la función combine de la clase Set que genera un array con la estructura deseada, que será el que le pasemos a la vista.$listadoProvincias = $this->Provincia->find('all', array('fields'=>array('id','nombre'),'order'=>'nombre ASC')); $this->set('provincias', Set::combine($listadoProvincias, "{n}.Provincia.id","{n}.Provincia.nombre"));La segunda función update_select, es a la que llamará el ajax para actualizar el listado de localidades a partir de un identificador de provincia.
Como se puede ver en el código, la función coge el identificador de provincia del select y envía a la vista los arrays actualizados de provincias y localidades.
Vistas
Localidades y provincias no tendrán vistas asociadas, ya que no hay ninguna operación en el controlador.
En clientes tendremos que crear la vista para la operación insertar del controlador, esta podría ser algo como esto:
/app/views/clientes/insertar.ctp echo $form->create('Inscripcione',array('action'=>'insertar')); echo $form->inputs(array('legend'=>'Actualizar Provincias', 'Localidade.provincia_id' => array('label'=> 'Provincia','showEmpty'=>'false','id'=>'provincias'), 'Alumno.localidade_id' => array('label'=> 'Localidad','showEmpty'=>'false','id'=>'localidades'), )); echo $form->end(); $options = array('url' => 'update_select','update' => 'localidades'); echo $ajax->observeField('provincias',$options);La vista será muy sencilla, un formulario con dos selects, uno de localidades y otro de provincias y una llamada al ajaxHelper en la que se indica que cada vez que se modifique el valor del select provincias, se llame a la función update_select y actualice el select de localidades.
Este select se actualizará con los valores devueltos por la vista de update_select, que lo único que hace es imprimir todos los nombres de localidades devueltos por la función del controlador.
/app/views/elements/update_select.ctp if(!empty($options)) { foreach($options as $k => $v) { echo"<option value='$k'>$v</option>";} }En este enlace se puede ver un ejemplo de funcionamiento.
Dudas de cakephp » dudas
Actualizar el contenido de un select con ajax.
(8 mensajes)-
Publicado hace 2 years #
-
Hola he seguido todo el script y cuando cargo la página aparece la primera provincia y sus localidades, pero al cambiar la selección recarga vacia las localidades.
Seguire investigando.Publicado hace 1 year # -
Aunque cuando utilizas ajax, el debug tiene que estar a 0, siempre puedes utilizarlo para comprobar que estás pasando correctamente el id de provincia, que estás llamando a la función correctamente y/o que la consulta a la base de datos no da ningún fallo.
También podrías utilizar el complemento firebug de firefox para chequear la petición ajax, de esta manera sabrías si le estás enviando el parámetro correcto y la respuesta de la petición.Publicado hace 1 year # -
hola buen dia, copie el codigo exacto, y al cambiar el primer combo no cambia los posteriores, alguien podria decirme q sucede¿¿¿
Publicado hace 1 year # -
Este código tiene problemas.
Podrias subir un zip con los archivos exactos para verificar?
Gracias.
Publicado hace 1 year # -
El codigo funciona bien, lo unico que le falta es:
<?php echo $javascript->link('jquery'); ?>
<?php echo $javascript->link('jquery.form'); ?>para que te funcione el ctp sino el javascript no hace nada.
Publicado hace 9 months # -
ALguien lo hice tan cual esta alli, pero no me actualiza las localidades alguien me podria colaborar? gracias!
Publicado hace 3 months # -
Amigos alguien sabe por qué no me guarda el campo provincias? todo me funciona bien pero cuando hago click en submit me guarda la localidad en la base de datos pero no la provincia y no sé por qué....
Publicado hace 2 months #