sábado, 23 de octubre de 2010

Kumbiaphp combos enlazados con JQuery [PHP combobox JQuery]

Hoy quiero compartir una solucion sencilla que muchos nos vemos en necesidad de implementar en nuestras aplicaciones web, esto es los combos enlazados, para quien no me entienda, me refiero cuando por ejemplo debes elegir primero un pais para ver sus ciudades.
Los que se acuerden de hace unos años atras antes de Ajax por lo usual se implementaba o con sencillos request http que te recargaba toda la pagina o utilizando iframes.Pues bien este ejemplo mostrará como hacer eso utilizando nuestro framework Kumbiaphp y JQuery.

Primero vamos a suponer que tienen una tabla Padre en mi ejemplo Tipocomponente y su tabla hija Grupocomponente.
Ahora vamos al codigo de nuestra aplicacion.
  1. Primero deben crear los modelos para ambas tablas, esto es que en la ubicacion [miapp]/app/models/ debe haber los archivos Tipocomponente.php y Grupocomponente.php
    Model : Tipocomponente.php
    class Grupocomponente extends ActiveRecord{
    
      public function listar(){
             return $this->find("order: 2 asc");
     }
    
    }
    

    Model : Tipocomponente.php
    class Tipocomponente extends ActiveRecord{
    
      public function listar(){
             return $this->find("order: 2 asc");
     }
    
     //lista los registros filtrados por el grupocomponente_id
     public function listar_por_grupo($grupo_id){         
             return $this->find("grupocomponente_id=$grupo_id","order: 2 asc");
     }
    }
    
  2.  Ahora debemos crear en [miapp]/app/models/ los controladores Tipocomponente_controller.php y Grupocomponente_controller.php
    Controlador : Grupocomponente_controller.php
    class GrupocomponenteController extends ApplicationController {
       public $models=array('grupocomponente');
       
    }
    

    Controlador : Tipocomponente_controller.php
    class TipocomponenteController extends ApplicationController {
       public $models=array('tipocomponente');
       public function listar_por_grupo($grupo_id){
           $this->lista=$this->Tipocomponente->listar_por_tipo($grupo_id);
       }
    }
    
    Para esta ultima accion del controlador Grupo, debemos crear su vista, usaremos este codigo y lo ubicaremos en [miapp]/app/views/grupocomponente/listar_por_grupo.phtml
    <?php echo select_tag("componente.grupocomponente_id", "id: grupos") ?>
    <?php
     foreach($grupos as $grupo):
    ?>
    <option value='<?php echo $grupo->id ?>'><?php echo $grupo->nombre ?></option>
    <?php endforeach; ?>
    </select>
    
  3. Por ultimo nuestra vista, supongamos que tenemos un controlador denominado Componente_controller.php el cual tiene una accion denominada crear y en la vista del mismo nombre osea crear.phtml (debe estar ubicado en [miapp]/app/views/componente/ ) es donde pondremos nuestro formulario.
    Nuestro nuevo controlador tendra un codigo similar a este:
    class ComponenteController extends ApplicationController {
      /**
      * otras acciones de nuestro controlador
      */
    
      public function crear(){
         $this->grupos=$this->Grupocomponente->listar();
         $this->marcas=$this->Marca->listar();
         $this->estados=$this->Estadocomponente->listar();
      }
    
    }
    
    El codigo de nuestra vista seria asi:
    <?php View::content(); ?>
    <div style='width: 450px;'>
    <h2>Nuevo Componente</h2> 
    <?php echo form_tag('equipo/crear/') ?>
    <fieldset>
    <legend>Datos de Componente</legend>
    <label>Tipo</label>
    <?php echo select_tag(array("componente.tipocomponente_id", $tipos, 'option' => 'nombre', 'include_blank'=> 'Seleccione...', 'tabindex: 1')); ?>
    <br />      
    <label>Grupo</label>
    <div id="grupos">
    <?php echo select_tag("componente.grupocomponente_id") ?>
    <option>Primero debe elegir un tipo de componente</option>
    </select>
    </div>
    <label>Marca</label>
    <?php echo select_tag(array("componente.marca_id", $marcas, 'option' => 'nombre', 'include_blank'=> 'Seleccione...')); ?>
    <br />   
    <label>Serie</label>
    <?php echo text_field_tag('componente.serie', 'size: 45') ?>
    <br />   
    <label>Modelo</label>
    <?php echo text_field_tag('componente.modelo', 'size: 35') ?>
    <br />
    <label>Estado</label>
    <?php echo select_tag(array("componente.estadocomponente_id", $estados, 'option' => 'nombre', 'include_blank'=> 'Seleccione...')); ?>
    <br />  
    <br />  
    <?php echo submit_tag("Guardar","id: save", "class: submit")?>
    <?php echo link_to("componente/","Cancelar", "class: cancel")?>
    </fieldset>
    </form>
    </div>
    
    

Ya tenemos todo listo para comenzar a codificar las interacciones en nuestra vista.
Nuestro formulario primero se mostrará 

Entonces vamos a ponerle algo javascript, agregaremos un evento que se activara en el momento que nuestro combo Tipo cambie. Para esto agregamos al final de nuestra vista un script el cual le dira a JQuery que escuche cuando se desate el evento change().
$('#componente_tipocomponente_id').change
Hasta ahora escucha nuestro evento, nos falta decirle que debe hacer cuando esto ocurre, eso lo hacemos poniendo algo asi:
$('#componente_tipocomponente_id').change(function(){ //codigo });

Bien ahora que es lo que queremos hacer ? bueno que cargue el combo Grupo. Entonces usando el metodo ajax de JQuery vamos a solicitar la url [miapp]/grupocomponente/listar_por_tipo y este nos devolvera un combo que se pintara en nuestra capa con id="grupos".
//capturamos el tipo_id de la opcion seleccionada
var tipo_id=$('#componente_tipocomponente_id').val();

//construimos nuestra url
/**
la constante PUBLIC_PATH contiene la ubicacion de publicacion de nuestra aplicacion, por ejemplo si estamos en un servidor local su valor seria
localhost/miapp/
*/
var _url="";
/**
Hacemos nuestra llamada AJAX por metodo POST
en el atributo data: enviamos nuestro parametro
y en success definimos que queremos suceda cuando la peticion sea exitosa
*/
$.ajax({   
    type: "POST",
    url: _url,
    data: "tipocomponente_id=" + tipo_id,
    success: function(data){
     //imprimimos el html proveniente de la vista listar_por_tipo dentro de la capa [div id="grupos"]
     $('#grupos').html(data);
    }
   });

Por ahora cada vez que cambiemos el valor en el combo, nuestra aplicacion hace la llamada y devuelve el valor, quedando nuestro formulario algo asi.

Pero vamos a agregarle interactividad, para esto simplemente agregamos este codigo antes de la llamada Ajax.

//imprime dentro del div[grupos] el gif animado de carga y la frase Buscando ...
$('#grupos').html('<span> <img src="<?php echo PUBLIC_PATH ?>/img/ui/ajax-loader.gif" /> Buscando ...</span>');

Ahora nuestra aplicacion cuando hay un cambio en combo y mientras se espera la respuesta muestra algo asi.

Bueno sera hasta otra entrada, espero les sirva de algo, si tienen algun comentario o sugerencia, excelente, asi aprendemos juntos ^_^.

9 comentarios:

  1. Buena tarde umm despues de ver tu ejemplo y de mirar como cargar un pequeño form con ajax al seleccionar un criterio de busqueda de un select creo que lo he logrado pero me encuentro con otro problema y es que si por ejemplo selecciono busqueda por nombre me carga bien el form y me hace bn la consulta sobre un paginador que tengo pero cuando selecciono otro criterio ejemplo 'por referencia' carga bn el form con ajax pero al enviar a filtrar por referencia no hace nada. Es decir funciona lo del ajax pero solo filtra por la primera opcion que se seleccione tengo lo siguiente:

    No se de primeraso pareciera que se deba resetear algo por allá interno no se, si alguien entiende mi problema le agradezco

    Tambien puede ser que usando mal el render o algo esta pasando con el POST cuando cambio de criterio(queda con la info del ultimo criterio seleccionado)

    ir a http://kumbiaphp.pastebin.com/76xK96xj

    No me dejo subir el codigo me dice que su html no es aceptable solo 4096 caracteres por eso te dejo el link

    ResponderEliminar
  2. Buenas, acabo de ver tu comentario, la verdad ahorita no te puedo dar una respuesta porque estoy en la oficina, pero hoy mismo te respondo mas tarde, vi tu codigo, interesante pero necesito verlo con mas detenimiento para poder ayudar.
    Saludos.

    ResponderEliminar
  3. Revisé tu código, y solo me queda la duda si no se te habrá pasado en el text_field_tag('nombre'), cambias de acuerdo a tu formulario, por ejemplo en referencia pones text_field_tag('referencia').

    ResponderEliminar
  4. Buena tarde, he dado con el error y es cada uno de mis formularios llamaba un mismo método del controlador y allí se decide si es por nombre, referencia, otros no se algo raro pasa que no me carga sino el último if que era el del nombre, entonces lo que hice fue separar por diferentes métodos y funciono.

    ResponderEliminar
  5. hola! excelente tuto... de casualidad no sabes como hacer Input con autocomplete jquery en KumbiaPHP beta 2????

    ResponderEliminar
  6. Me alegro que te haya servido, la verdad no he probado la beta 2 pero pronto lo hare y posteare el tutorial

    ResponderEliminar
  7. Hola buen tuto!!!... he utilizado algunas cosas para mejorar mi form, muchas gracias.

    Tengo una pregunta, sucede que en mi formulario cargo los select_tad con información de mi base de datos, específicamente la localidad. Para esto me valgo de ajax, pero cuando estoy en mi form, elijo la localidad y le doy enviar, el id de la ciudad seleccionada no se envía ya que ese select_tag se muestra mediante ajax desde otra parte.

    Mi pregunta es si sabes como obtener el id de la ciudad seleccionada para que ese formulario se guarde.

    de antemano, muchas gracias

    ResponderEliminar
  8. Hola, que bueno que te haya servido el tuto, por lo que me dices tu select_tag no se encuentra dentro del formulario, si es asi, podrias colocar un control input hidden donde almacenas el id elegido, esto lo tendrias que hacer con Javascript.
    Pero si el select_tag si es dentro de tu formulario y al enviarlo no lo recibes no es por el ajax, fijate que el name de tu control sea el correcto.
    Por lo usual los helper de kumbiaphp utilizan el patron controlador.nombre_del_campo
    Asi verbigrate en tu formulario seria algo como micontrola.localidad_id
    Para mayor seguridad haz un traceo de los datos, mejor dicho imprime en pantalla los datos que recibes, tb puedes utilizar el firebug

    ResponderEliminar
  9. podrias subir los archivos con el ejemplo por favor

    ResponderEliminar

 
Powered by Blogger