ajax y jquery en cakephp

En este post voy a explicar como es de simple usar ajax y jquery en cakephp.
Se puede usar ajax para muchos temas, guardar los checkbox de un formulario sin tener que hacer submit, para seleccionar subcategorias de una categoría en varios select option aninados, para recargar el contenido de una determinada zona de la web, en general para muchas cosas pero siempre que se necesite.

En este caso voy a explicar como usar menus desplegables con ajax y jquery.
De manera que teniendo un menú select option con una serie de categorías al seleccionar una de ellas te aparezcan sus subcategorías.

Básicamente necesitamos descargar y subir la librería de jquery a nuestro servidor o usar la que hay en Google Code, crear nuestro formulario con una serie de id que son los elementos que harán de “bindeo” con jquery, una función en nuestro controlador que busque las subcategorias de la categoria dado el id y una vista para renderizar el select option con las subcategorías que hemos obtenido

Lo explico con mas detalle.

1.- INSERTAR LA LIBRERÍA DE JQUERY
Sino nada va a funcionar, podéis incluir directamente este fragmento de código entre las etiquetas <head></head>

<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>

2.- EL FORMULARIO
Tener una vista o un HTML donde tengáis un formulario.
En el formulario habrá que crear un identificador para el select option en este caso he puesto

id="select_categoria"

Este es un select option de ejemplo, faltaría poner todo el html que vosotros necesitéis, pero para explicarlo con sólo esto es suficiente

<select id="select_categoria">
  <option value="1">categoria1</option>
  <option value="2">categoria2</option>
  <option value="3">categoria3</option>
</select>

También habrá que crear un div o un p para que cuando se devuelva el select option con las subcategorias se pinten en dentro de un html. Lo ideal sería ponerlo después del select option para que las subcategorias se visualicen a continuación

<div id="div_subcategorias_wrapper"></div>

3.- LAS FUNCIONES JQUERY

Este puede que sea el paso mas difícil de todo el proceso

El id que hemos puesto al select option de las categorías se utiliza para que jquery haga un bindeo a una determinada acción que nosotros especifiquemos. En este caso estamos bindeando que el id select_categoria, en jquery se definen mediante el símbolo # (por si alguien no lo sabe y esta algo perdido) se binde a una accion de click, por lo que cuando se seleccione una categoría haciendo click sobre ella se lanza la función siguiente de jquery.
Se hace una llamada ajax $.ajax(); con una serie de parámetros
type: si es GET o POST
url: la url a la que llamamos para obtener la información necesaria, $(this).val() es el valor de la categoría que he seleccionado, en este caso si identificador por el que buscaré sus subcategorías relacionadas
beforeSend: (antes de enviar) lo que hago es meter en el div que hemos creado para pintar los select option de las subcategorias, meto un div con un gif animado, esto da el efecto como que se esta cargando algo y el usuario entiende que tiene que esperar. El gif que verían sería algo como esto:
success: cuando ha terminado y se devuelve la información, se genera la variable msg (yo la he llamado así) que contiene el resultado de lo que se ha ejecutado en el controlador, simplemente lo insertamos en el div anterior y ya tendríamos los select option cargados dinámicamente.


$("document").ready(
function() {

    $('#select_categoria').bind('click', function()
    {
        $.ajax({
               type: "GET",
               url: "/articulos/obtener_subcategorias/"+$(this).val(),
               beforeSend: function() {
                     $('#div_subcategorias_wrapper').html('<div class="rating-flash" id="cargando_div">Cargando  <img src="/img/ajax-loader_mini.gif"></div>');
                     },
               success: function(msg){
                   $('#div_subcategorias_wrapper').html(msg);
               }
             });
    });

}
);

4.- El CONTROLADOR O LA LÓGICA DE PHP

Esta parte es variable, yo estoy explicando el ejemplo para quien usa CakePHP pero se puede hacer en php puro si se quiere u otro framework.

También hay que tener cuenta que el siguiente controller es de ejemplo, y sirve como guía para quien ya sepa CakePHP.

<?php
class ArticulosController extends AppController
{
    var $uses = array('Articulo','ArticuloCategoria','ArticuloSubcategoria');
    function index()
    {
        // lógica
    }

    function obtener_subcategorias($id)
    {
        $this->layout = 'ajax';
        // aquí la lógica que uséis para obtener datos de la base de datos
        // y generar un array con todas las categorías
        // por lo normal y rápido será usar la funcion find con el primer parámetro list para que lo devuelva formateado con el identificador de cada opcion como key de los nodos del array
        $subcategorias = $this->ArticuloSubcategoria->find('list',array('conditions' => array('ArticuloSubcategoria.categoria_id' => $id), 'fields' => 'nombre_subcategoria'));
        $this->set('listado_subcategorias',$subcategorias);
    }

}
?>

5.- RENDERIZAR EL SELECT OPTION EN LA VISTA

Renderizar el resultado de lo que hemos obtenido en la función obtener_subcategorias() en la vista
Necesitaremos crear la vista /app/views/articulos/obtener_subcategoria.ctp

<? echo $form->input('Articulo.id_subcategoria', array('options' => $listado_subcategorias,'label'=>false,'div'=>null));?>

Y listo! el resultado lo recoge el ajax y lo pinta en el div que hemos explicado anteriormente.

Es muy sencillo usar AJAX con JQUERY, integrarlo con CakePHP puede ser algo mas liado hasta que lo haces la primera vez.

Cualquier duda o comentario no dudéis en escribirlo.

23 opiniones en “ajax y jquery en cakephp”

  1. Hola amigo soy de Perú estudiante de ingeneria de sistemas y bueno estoy de curioso sobre el framework (CAKEPHP) y me interesa, kisiera una aplicacion de login pero que ya este funcionando talves puedas ponerlo en un archivo .rar para poderlo descargar te agradesco de antemano. SALUDOS DESDE PERU

  2. Que tal pedro

    oye te queria consultar, que me recomiendas..

    estoy utilizando directamente el ajax mediante el helper de cake de la siguiente forma

    $this->Js->get(‘.delete_task’)->event(‘click’, $this->Js->request( array(‘controller’ => ‘tasks’, ‘action’ => ‘task’, ‘delete’,$task[‘Task’][‘id’]),
    array(
    ‘update’ => ‘#taski’,
    ‘async’ => true,
    ‘asuccess’ => QUE HACER,
    ‘dataExpression’ => true,
    // ‘success’ => $this->Js->serializeForm(‘#observacion’)->effect(‘fadeIn’),
    ‘method’ => ‘post’,
    ‘data’ => $this->Js->serializeForm(array(‘isForm’ => true, ‘inline’ => true))
    )
    )
    );

    pero no consigo la forma de integrarle una funcion success para dar respuesta del envento realizado.
    no se si lo haga o tendre que utilizar el jquery directamente para hacer el get, ya que poor alli si veo que el success seria una funcion normal de respuesta

    espero me puedas ayudar

    gracias

    saludos

  3. Hola Muy buen post la verdad me sirvió mucho Gracias, solo que todo me sale bien pero al insertar en la base de datos no me inserta el valor de la lista alguna idea?

  4. He seguido su guía y me a funcionado perfectamente, cuando lo intento hacer ha mas niveles no funciona, no es posible traer una tercera lista.

    Ejemplo: tengo estados que al seleccionarlos me extraer los municipios, cuando selecciono algún municipio no me extraer la ciudades.

    Hay algo que se me esta pasando?

    Un saludo y gracias desde ya.

    1. Esto es más complejo.
      Puedes crear todas las funciones con los bindeos de todos los select option con las funciones .bind(‘click’, function() pero recuerda que para que funcionen el html y los identificadores de todos los “click” de los select option tienen que existir cuando se carga el script, es decir cuando hace el $(“document”).ready(). Sino existe el identificador + el html asociado, el bindeo de jquery no funciona.

      No se si te queda claro…

      Prueba a crear todo el formulario con los municipios y ciudades con un select option, pero que tengan un id asigando luego cuando se vayan sustituyendo por ajax con los resultados del anterior filtrado por estados, tendrás que crear el select option de municipios con el mismo id, y así con el de ciudades.

      Prueba a hacer esto a ver si te funciona, y me cuentas…

      1. Hola Pedro, muchas gracias por responder, al final parte de lo que me comentas no lo habia tenido en cuenta.

        Pude solucionarlo con funciones .live(‘click’, function(), live en lugar de bind.

        Gracias por su tiempo.

  5. Hola:

    Que buena explicacion, lo he implementado y ha funcionado, sigue haciendo mas tutoriales como este, para los que estamos comenzando con cakephp, ya que hay pocos sitios con informacion confiabley exacta, sobre este framework.

  6. Buenas! Thnks por el materia!. Soy nuevo en el mundo de cake, y tengo una pregunta… dónde metes el código jquery del apartado 3??? me podrías especificar carpeta/archivo?? muchas gracias!

  7. hola genial, pense q Cakephp no estaba manejando Jquery y ya eso era desventajoso, pero veo q si se puede utilizar este framework JQUERY, bueno me gustaria q hicieras un tutorial o todo un curso de CAKEPHP utilizando JQUERY, subelo a youtube te aseguro q como yo hay muchos q no se animan porq no saben q SE puede utilizar jquery con cakephp. mantenme al tanto amigo.

  8. Hola, muy bueno el Post, por casualidad tendrá un mismo ejemplo pero con checkbox relacionados a los modelos?…..
    lo he intentado adaptar pero no me funciona… gracias de antemano….

  9. Sabes, me funciona la idea, pero cuando muestro el nuevo div, me muestra toda la pagina en el div, no me muestra la plantilla .ctp con el nuevo select, a que se deberia ???
    de antemano muchas gracias por la explicación.

    1. Has probado a renderizar sobre un layout vacío? Quizá ese es el problema..
      Dime si fue eso, sino coméntame mas detalles del error a ver si te puedo ayudar.
      Un saludo!

  10. Saludos,

    Probé con el alert(msg) y no muestra nada,
    Revisé la cónsola de error de firefox y aparece limpia
    Agregué la función error y aparecen tres mensajes: 1.- “[object XMLHttpRequest]” 2.- error 3.- undefinied

    Gracias por tu ayuda

    1. Seguro que es algo de programación revisa el código, el controller que yo he puesto es una guía para quien ya sabe algo de CakePHP.
      He metido algunos destalles mas en el controller por si te sirven de ayuda.

  11. Hola,

    En la vista no carga el select con las subcategorias en el #div_subcategorias_wrapper,

    Aparece la imagen ajax-loader_mini y se queda allí, me está funcionando bien la consulta de las subcategorias, la probé en la vista aparte.

    1. Prueba a poner un alert(msg) para ver que te está devolviendo el ajax en la parte de success:

       $.ajax({
                     type: "GET",
                     url: "/articulos/obtener_subcategorias/"+$(this).val(),
                     beforeSend: function() {
                           $('#div_subcategorias_wrapper').html('<div class="rating-flash" id="cargando_div">Cargando  <img src="/img/ajax-loader_mini.gif"></div>');
                           },
                     success: function(msg){
                      alert(msg);
                     }
                   });
      

      También prueba a meterle en la consulta ajax un evento adicional, error:

      error: function(XMLHttpRequest, textStatus, errorThrown){
                  alert(XMLHttpRequest);
                  alert(textStatus);
                  alert(errorThrown);
                     }
      

      Si necesitas mas datos sobre la sintaxis de error mirate la web de jquery: http://api.jquery.com/jQuery.ajax/

      Si usas firefox y firebug mira a ver en consola que te aparece, si te devuelve la consulta al ajax con una cabecara 200 (si esta ok), o si te devuelve otro tipo de error. Prueba a meterle también al controlador el debug para ver si hay algún error de programación

      Configure::write('debug',3);
      

      No se que mas te puedo decir, para ayudarte a debugear esto sin poder ver el código.. ya me vas contando..

      1. Saludos,

        1.-Probé colocando el alert(msg) y no envía nada.
        2.- Ví en la cónsola de error, aparece limpia.
        3.- Agregué la función de error y envía tres mensajes:
        El primero: object XMLHttpRequest
        El segundo: error
        El tercero: undefinied

        Gracias por tu ayuda

        1. pues si pusiste el alert(msg) y no te devuelve nada directamente es que hay algo mal.
          Pues vamos a ver, por pasos, habrá que descargar que sea un fallo de la programación.

          Mete en la funcion del controller

          Configure::write('debug',3);
          

          Prueba a llamar a la url directamente desde el navegador, tipo: TU_PROYECTO.loc/articulos/obtener_subcategorias
          suponiendo que tu controlador se llama articulos, tienes la función que he indicado y que tienes el respectivo modelo, tienes la respectiva vista creada, la tabla con las subcategorias
          Si esto te esta devolviendo un select option con las subcategorias, hasta aquí todo bien, después habrá que ver si es algo de ajax o jquery

          Yo me he tenido que pelar mucho con este tipo de cosas hasta que me ha salido 😉

          1. Efectivamente, tengo creada las tablas en la base de datos, los modelos y las vistas. He probado la ruta /proyecto/usuarios/obtener_subcategoria/1 y correctamente me devuelve un select con las categorias respectivas,

            El problema está es en el código jquery:

            success: function(msg) { $(‘#div_subcategorias_wrapper’).html(msg); }

            No me devuelve (no renderiza) el select en el div. Lo que falta es que lo pinte ahí y desaparezca la imagen de espera.

            He probado agregando el component Ajax en el controller

          2. me respondo a mi mismo.
            El problema que tenía es que la linea:
            url: “/articulos/obtener_subcategorias/”+$(this).val(),
            del js en mi caso no funciona (no sé por qué), sino que tengo que poner la ruta desde localhost completa.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *