Añadiendo AJAX en CodeIgniter con jQuery

Publicado: 17/12/2009 en AJAX, CodeIgniter, desarrollo, JavaScript, jQuery, php
Etiquetas:, , , , ,

You can read the English version of this post in http://phpsblog.agustinvillalba.com/adding-ajax-codeigniter-jquery/

Hoy vamos a hablar sobre cómo añadir AJAX al framework de desarrollo PHP CodeIgniter. Cuando comencé a trabajar con este framework me resultó bastante extraño que no tuviera bastante avanzada la integración de AJAX en él, dado que es un framework relativamente nuevo y la metodología AJAX lleva ya unos años expandiéndose en el desarrollo web. Dado que esta semana me ví en la necesidad de integrar AJAX en mi aplicación CodeIgniter y el framework de JavaScript jQuery, he estado buscando mucha información sobre este tema en la red y la verdad es que, además de estar muy dispersa, no es muy abundante y tampoco muy clara, así que aquí va mi aportación a partir de lo que he aprendido, espero sea de utilidad.

Desarrollando nuestro controlador

Bien, para explicar la integración de jQuery en CodeIgniter vamos a poner un caso de ejemplo con el que trabajar. En una web deportiva necesitamos editar la ficha de un partido, para ello tenemos un lista desplegable (tag select) en la que mostramos una serie de torneos y otra lista desplegable vacía en la que mostramos los partidos. La lista de partidos ha de rellenarse (mediante AJAX) con cada cambio que se produzca en la lista de torneos, mostrando los partidos del torneo seleccionado cada vez. Para ello hemos de crear nuestro controlador de edicion de ficha, con este código:

class Ficha extends Controller {

 public function __construct()
 {
 parent::Controller();
//Cargamos el modelo de torneo
 $this->load->model('tournament_model');
 }

...
...

 public function edit_ficha()
 {
//Obtenemos todos los torneos del sistema
 $data["tournaments"] = $this->tournament_model->get_tournaments();
//Cargamos la vista de edición de una ficha de partido
 $this->load->view('edit_ficha',$data);
 }
...
...
}

Con esto ya tenemos nuestro controlador de edición de fichas de partidos, ahora viene una de las partes importantes del proceso y es crear la vista de edición de fichas, donde residirá nuestro código JavaScript con jQuery con el cual realizaremos las peticiones de datos vía AJAX. Aquí podemos ver el código de la vista de edición de fichas:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>  //Incluimos el framework jQuery desde su propia web
<script type="text/javascript">
 $(function() { //En cuanto esté listo el DOM, deshabilitamos la lista de partidos
 $('select#match_list').attr('disabled',true);
 });

 function activate_match()
 {
 var tnmt_id = $('select#tournament_list').val(); //Obtenemos el id del torneo seleccionado en la lista
 $.ajax({
 type: 'POST',
 url: '<?php echo base_url(); ?>index.php/match/list_dropdown', //Realizaremos la petición al metodo list_dropdown del controlador match
 data: 'tnmnt='+tnmt_id, //Pasaremos por parámetro POST el id del torneo
 success: function(resp) { //Cuando se procese con éxito la petición se ejecutará esta función
 //Activar y Rellenar el select de partidos
 $('select#match_list').attr('disabled',false).html(resp); //Con el método ".html()" incluimos el código html devuelto por AJAX en la lista de partidos
 }
 });
 }
</script>

<strong>Tournament:</strong>
<select id="tournament_list" onchange="activate_match()">
 <?php
 foreach($tournaments as $tournament)
 {
 echo "<option value='{$tournament["id"]}'>{$tournament["name"]}</option>";
 }
 ?>
</select>
<br />
<strong>Match:</strong>
<select id="match_list" onchange="show_clips()">

</select>

Con el código anterior hemos realizado la petición por AJAX al controlador de partidos (“match”), en concreto al método list_dropdown(). He de remarcar una cosa que me dió bastantes dolores de cabeza hasta que lo descubrí, y es que es muy importante poner index.php en la url del controlador de destino, dado que si no lo ponéis no funcionará, a menos que tengáis un archivo .htaccess en vuestro directorio web en el que tengáis una regla para evitar poner index.php en la url.

El método list_dropdown() procesará la petición, trayendo los partidos del torneo en cuestión y cargando la vista de la lista. Aquí tenemos el código de controlador de nuestro partido:

class Match extends Controller {

 public function __construct()
 {
 parent::Controller();
 $this->load->model('match_model');
 $this->load->model('team_model');
 }

 public function index()
 {

 }

 public function list_dropdown()
 {
 $tnmnt_id = $this->input->post('tnmnt'); //Recogemos el identificador del torneo pasado por POST
 $matches = $this->match_model->get_match_by_tournament($tnmnt_id); //Obtenemos los partidos del torneo
 $teams = array(); //Almacenaremos los nombre de los equipos de la forma "id_equipo" => "nombre_equipo"
 if(!empty($matches))
 {
 foreach($matches as $match)
 {
 if(!array_key_exists($match["teama"], $teams))
 {
 $team_name_A = $this->team_model->get_team_name($match["teama"]);
 $teams[$match["teama"]] = $team_name_A;
 }
 if(!array_key_exists($match["teamb"], $teams))
 {
 $team_name_B = $this->team_model->get_team_name($match["teamb"]);
 $teams[$match["teamb"]] = $team_name_B;
 }
 }
 }
 $data["matches"] = $matches;
 $data["teams"] = $teams;
 $this->load->view('list_dropdown_view',$data);
 }
}

Por último, ya sólo nos queda crear la vista de la lista desplegable de partidos. Esto no será más que un archivo en el que se escriban todos los tag option de la lista desplegable que se cargarán en el select de los partidos. El código sería el siguiente:

if(empty($matches))
 {
 echo "<option value=''>No available matches</option>";
 }
 else
 {
 foreach($matches as $match)
 {
 echo "<option value='{$match["id"]}'>{$teams[$match["teama"]]} - {$teams[$match["teamb"]]}</option>";
 }
 }

Con esto ya tendríamos nuestra vista y tendríamos concluida nuestra integración de jQuery en CodeIgniter para poder usar AJAX. Como resultado, en la vista de ficha de partido, cada vez que cambie el elemento seleccionado en la lista de torneos, se actualizará la lista de partidos de ese torneo. En otro post podremos hablar largo y tendido sobre el framework jQuery y su funcionamiento con AJAX y en general.

You can read the English version of this post in http://phpsblog.agustinvillalba.com/adding-ajax-codeigniter-jquery/

Anuncios
comentarios
  1. LEonardo dice:

    por favor puedes subir tu trabajo de codeIgniter + la base
    xfaaaaa

  2. natalia dice:

    Hola, gracias por el ejemplo pero me salto una duda.
    En que parte deberia ir esta parte de codigo:
    //Incluimos el framework jQuery desde su propia web

    $(function() { //En cuanto esté listo el DOM, deshabilitamos la lista de partidos
    $(‘select#match_list’).attr(‘disabled’,true);
    });

    Gracias

  3. Ricardo Chi dice:

    Excelente, estuve buscando como implementar Ajax en CI, y la verdad, yo con 0 conocimiento de Ajax pude usar tu ayuda para realizar lo que quiero, que es algo muy parecido a tu ejemplo.

    Realmente Gracias!

  4. MoySal dice:

    Gracias por este codigo… me sirvio bastante… solo una duda… como se haría para que desde inicio no este bloqueado y muestre los partidos del torneo que se esta presentando

    • Simplemente en tu vista, una vez has cargado la librería jQuery, simplemente has de eliminar la línea:
      $('select#match_list').attr('disabled',true);

      Con eso, la lista de partidos continuaría habilitada.

      Saludos.

      • MoySal dice:

        ya quite ese linea, y si, queda habilitada desde un principio, pero no me muestra los partidos del torneo que se esta presentando… que mas hay que hacer para que me muestre los partidos desde un inicio?

  5. Sergio Javier dice:

    Solo a modo adicional para que le quede claro a alguien que no entendio, le paso un link con un ejemplo muy claro, el cual es muy util para ubicarte: http://www.jqueryeasy.com/2012/02/07/mostrar-html-dinamico-con-ajax-en-codeigniter/

  6. ozz dice:

    hola muy bueno tu blog la verdad…..entiendo algo de php pero esto de del MVC me esta haciendo doler la cabeza,tengo una lista desplegable con dni y nombre y cuando elijo uno me muestra los datos en una lista clasica, pude hacerlo con ayax y php pero al momento de hacerlo en codeigniter me dice que mi funcion en el controlador no funciona! este es mi codigo sin codeigniter:
    archivo getuser.php:

    y el archivo con ayax:

    function showUser(str)
    {
    if (str==””)
    {
    document.getElementById(“txtHint”).innerHTML=””;
    return;
    }
    if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
    xmlhttp=new XMLHttpRequest();
    }
    else
    {// code for IE6, IE5
    xmlhttp=new ActiveXObject(“Microsoft.XMLHTTP”);
    }
    xmlhttp.onreadystatechange=function()
    {
    if (xmlhttp.readyState==4 && xmlhttp.status==200)
    {
    document.getElementById(“txtHint”).innerHTML=xmlhttp.responseText;
    }
    }
    xmlhttp.open(“GET”,”getuser.php?q=”+str,true);
    xmlhttp.send();
    }

    <?php
    echo "”;

    $conexion = mysql_connect(“localhost”,”root” , “”)
    or die (“Problemas con la conexion”);
    mysql_select_db(“sistemcp” , $conexion) or die (“Problemas con la BD”);

    $result=mysql_query(“SELECT pac_dni , pac_nom FROM pacientes;” ,$conexion) or die (“problema en el query”);

    while($fila=mysql_fetch_array($result)){
    echo ”.$fila[“pac_dni”].’ – ‘.$fila[“pac_nom”].”;
    }

    echo ”;

    ?>

    Person info will be listed here.

    como hago que al elegir el item los datos me los muestre en la vista actual por ayax?

    • Hola ozz!

      Lo primero comentarte que para pasar tu código al patrón MVC has de separar la conexión a la BD (el modelo) y el código que procesa los resultados (el controlador). No sé cómo tienes hecho el controlador de CI ni el error que CI te está dando. Pero lo primero es comentarte que para poder cargar una respuesta AJAX desde el controlador y enviarla al navegador cliente, has de cargarla en una vista de CI en la que has de mostrar esa lista clásica con lo que te haya llegado de la base de datos.
      Si me pasas el código del controlador que te está dando problemas te podré ayudar mejor.
      Saludos!

  7. kevin martinez (@n4utilius) dice:

    gracias por el articulo, me ha servido mucho, ahora sigo tu blog, y cuando tenga un poco mas de tiempo checo tus post 🙂

  8. Ronald Blanco dice:

    Un gran saludo Agustín, tu articulo me parece muy interesante, pero la verdad yo soy aún nuevo en este framework que es CodeIgniter. por esa razón se me hizo muy dificil poner en funcionamiento el código que proporcionaste arriba, debido a que no hallo el código del modelo tournament_model 😦 y los otros modelos a los que llaman tus controladores
    Además no se si me tengo que crear otro directorio para las funciones JQuery.
    Te agradeceria mucho si me facilitaras el código en un rar porfaa mi correo es ronnmail@gmail.com
    Desde ya muchas gracias…

    • Hola Ronald,
      Verás, el modelo tournament_model es uno que yo me inventé para el ejemplo. Debes sustituirlo por tus propios modelos. Lo mismo con los controladores. En cuanto a las funciones jQuery, puedes ponerlas en un directorio llamado js en la raíz de tu aplicación web. En cuanto al código fuente… el que está publicado es todo el código fuente, me lo inventé sobre la marcha para el ejemplo, ese es todo el código.
      Saludos!

  9. Jose Fernandez dice:

    hola, e aplicado tu ejemplo de los select, me funcionan muy bien gracias por la publicacion. el inconveniente que tengo es que el navegador de google el chrome no funciona, quisa conoces ho hay una menera que este mismo codigo funciones en este navegador. en IE. Firefox funcionana muy bien.

  10. andrei dice:

    Hola amigo

    Soy nuevo en CodeIgniter y estoy haciendo una aplicacion en donde necesito usar algo como este ejemplo, pero he buscado bastante en internet y no he podido encontrar algun ejemplo que me ayude o me explique bien sobre el tema de ajax con base de datos en codeigniter pero en esta forma en que lo explicas específicamente. Esto lo domino bastante en php, pero no lo se migrar para este framework. De todas las formas que he tratado no he obtenido los resultados que deceo.
    ¿Como pudiera descargar este ejemplo que colocaste pero con los model para hacerlo andar y así aclarar mis dudas?

    Gracias

    • Hola Andrei,
      Si no entiendo mal tu pregunta, lo que tu necesitas es, ampliando mi explicación del artículo, es en el controlador al que AJAX realiza la llamada, añadir la llamada a tu modelo que se conecte a la base de datos, algo parecido a esto:

      ...
      $this->load->model('tu_modelo');
      $result = $this->tu_modelo->tu_funcion_en_el_modelo();
      ...

      Espero que esto sea lo que necesitas y haber aclarado tu duda.
      Un saludo!

      • andrei dice:

        Hola Agustin

        Lo que me pasa es lo siguiente:
        En el sistema que estoy haciendo tengo un menu que al presionar un boton me carga un controlador que a su vez llama a un model donde busca todos los clientes de una base de datos y estos resultados actualizan un SELECT, pero este select está en un div oculto que se despliega en la opcion onclick del boton. Esto funciona a medias ya que me despliega el div pero no me actualiza el selec.
        Cuando cargo el view se carga el header.php, contenido.php y footer.php

        ===============================
        Controlador contratos.php
        ===============================
        load->model(‘users’); //usuarios de login
        $this->load->model(‘clientes’); //clientes de contratos

        $this->userid = $this->session->userdata(‘userid’);
        if (!isset($this->userid) or $this->userid==”) redirect(‘login’);
        }

        function index()
        {

        $this->load->helper(‘url’);
        $data[‘page_title’] = ‘Contratos’;
        $data[‘display_login’] = ‘display:none;’; //status del div login
        $data[‘display_menu’] = ”;
        $data[‘lista_clientes’] = $this->clientes->obtener_clientes();//pido el listado de clientes existentes

        //creo el array con datos de configuración para la vista
        //$datos_vista = array(‘lista_clientes’ => $clientes, ‘page_title’=> $data[‘page_title’], ‘display_login’=> $data[‘display_login’],
        //’display_menu’=> $data[‘display_menu’]);
        $datos_vista = array(‘page_title’=> $data[‘page_title’], ‘display_login’=> $data[‘display_login’],
        ‘display_menu’=> $data[‘display_menu’]);

        $this->load->view(‘contratos/index’, $datos_vista);
        //$this->load->view(‘contratos/index’, $data);

        }

        function clientes()
        {
        $this->load->helper(‘url’);

        //Busco de la base de datos mediante los modelos
        $this->load->model(‘clientes’);
        $data[‘lista_clientes’] = $this->clientes->obtener_clientes();//pido el listado de clientes existentes

        //creo el array con datos de configuración para la vista
        $datos_vista = array(‘lista_clientes’ => $clientes);

        if ($datos_vista==false)
        {
        //$this->load->view(‘clientes/index’, $data);
        echo ‘No existen Clientes’;
        }
        else
        {
        //$this->load->view(‘contratos/clientes’, $datos_vista);
        //return $datos_vista;
        $datos_vista = array( ‘lista_clientes’=> $data[‘lista_clientes’]);
        $this->load->view(‘clientes/index’, $datos_vista);

        }

        }

        function logout() {

        $this->load->helper(‘url’);
        $this->session->sess_destroy();
        $data[‘display_login’] = ”;
        $data[‘display_menu’] = ‘display:none;’;
        redirect(‘login’, $data);
        }

        }

        ===============================
        Vista index.php
        ===============================
        load->view(‘header’);
        ?>

        <a class="logout" href="”>Cerrar sesión

        load->view(‘contratos/contratos’); ?>

        load->view(‘footer’);
        ?>

        ===============================
        vista contratos.php
        ===============================

        load->view(‘contratos/new_contrato’);
        ?>

        Sistema de Contratos

        <a href="” class=”root_invoices”>Contratos
        <a href="” class=”root_clients”>Clientes
        <a href="” class=”root_reports”>Reportes

        ===============================
        vista newcontrato.php
        ===============================

        Nuevo Contrato

        — —

        <?
        foreach ($lista_clientes as $clientes){
        echo 'id_cliente.'” >’.$clientes->nombre.”;
        }
        ?>

        <input type="submit" value="” name=”crearcontrato” id=”crearcontrato” class=”art-button” onclick=”fn_cerrar();”/>
        <input type="button" value="” id=”crearcontratocancel” class=”art-button” onclick=”mostrarPanel(‘enlacepanel1′,’panel1’);”/>

        <!– –>

        ===============================
        model clientes.php
        ===============================
        db->order_by(‘nombre’)->get(‘clientes’);

        if($query->num_rows > 0){

        foreach ($query->result() as $clientes){
        $data[] = $clientes;
        }
        return $data;

        }
        }
        }

        ===============================
        el boton del menu esta en header.ph y esta es su descripcion
        ===============================
        ……
        ……

        <a href=" ” onClick=”mostrarPanel(‘enlacepanel1′,’panel1’); return false;”>Nuevo Contrato

      • andrei dice:

        Hola Agustin

        Lo que me pasa es lo siguiente:
        En el sistema que estoy haciendo tengo un menu que al presionar un boton me carga un controlador que a su vez llama a un model donde busca todos los clientes de una base de datos y estos resultados actualizan un SELECT, pero este select está en un div oculto que se despliega en la opcion onclick del boton. Esto funciona a medias ya que me despliega el div pero no me actualiza el selec.
        Cuando cargo el view se carga el header.php, contenido.php y footer.php

        ===============================
        Controlador contratos.php
        ===============================
        load->model(‘users’); //usuarios de login
        $this->load->model(‘clientes’); //clientes de contratos

        $this->userid = $this->session->userdata(‘userid’);
        if (!isset($this->userid) or $this->userid==”) redirect(‘login’);
        }

        function index()
        {

        $this->load->helper(‘url’);
        $data[‘page_title’] = ‘Contratos’;
        $data[‘display_login’] = ‘display:none;’; //status del div login
        $data[‘display_menu’] = ”;
        $data[‘lista_clientes’] = $this->clientes->obtener_clientes();//pido el listado de clientes existentes

        //creo el array con datos de configuración para la vista
        //$datos_vista = array(‘lista_clientes’ => $clientes, ‘page_title’=> $data[‘page_title’], ‘display_login’=> $data[‘display_login’],
        //’display_menu’=> $data[‘display_menu’]);
        $datos_vista = array(‘page_title’=> $data[‘page_title’], ‘display_login’=> $data[‘display_login’],
        ‘display_menu’=> $data[‘display_menu’]);

        $this->load->view(‘contratos/index’, $datos_vista);
        //$this->load->view(‘contratos/index’, $data);

        }

        function clientes()
        {
        $this->load->helper(‘url’);

        //Busco de la base de datos mediante los modelos
        $this->load->model(‘clientes’);
        $data[‘lista_clientes’] = $this->clientes->obtener_clientes();//pido el listado de clientes existentes

        //creo el array con datos de configuración para la vista
        $datos_vista = array(‘lista_clientes’ => $clientes);

        if ($datos_vista==false)
        {
        //$this->load->view(‘clientes/index’, $data);
        echo ‘No existen Clientes’;
        }
        else
        {
        //$this->load->view(‘contratos/clientes’, $datos_vista);
        //return $datos_vista;
        $datos_vista = array( ‘lista_clientes’=> $data[‘lista_clientes’]);
        $this->load->view(‘clientes/index’, $datos_vista);

        }

        }

        function logout() {

        $this->load->helper(‘url’);
        $this->session->sess_destroy();
        $data[‘display_login’] = ”;
        $data[‘display_menu’] = ‘display:none;’;
        redirect(‘login’, $data);
        }

        }

        ===============================
        Vista index.php
        ===============================
        load->view(‘header’);
        ?>

        <a class="logout" href="”>Cerrar sesión

        load->view(‘contratos/contratos’); ?>

        load->view(‘footer’);
        ?>

        ===============================
        vista contratos.php
        ===============================

        load->view(‘contratos/new_contrato’);
        ?>

        Sistema de Contratos

        <a href="” class=”root_invoices”>Contratos
        <a href="” class=”root_clients”>Clientes
        <a href="” class=”root_reports”>Reportes

        ===============================
        vista newcontrato.php
        ===============================

        Nuevo Contrato

        — —

        <?
        foreach ($lista_clientes as $clientes){
        echo 'id_cliente.'” >’.$clientes->nombre.”;
        }
        ?>

        <input type="submit" value="” name=”crearcontrato” id=”crearcontrato” class=”art-button” onclick=”fn_cerrar();”/>
        <input type="button" value="” id=”crearcontratocancel” class=”art-button” onclick=”mostrarPanel(‘enlacepanel1′,’panel1’);”/>

        <!– –>

        ===============================
        model clientes.php
        ===============================
        db->order_by(‘nombre’)->get(‘clientes’);

        if($query->num_rows > 0){

        foreach ($query->result() as $clientes){
        $data[] = $clientes;
        }
        return $data;

        }
        }
        }

        ===============================
        el boton del menu esta en header.ph y esta es su descripcion
        ===============================
        ……
        ……

        <a href=" ” onClick=”mostrarPanel(‘enlacepanel1′,’panel1’); return false;”>Nuevo Contrato

        esta actualizacion del select quiero hacerla con ajax, pero asi todo quisiera saber hacerlo por esta via tambien.

        mi correo es andrei@oc.quimefa.cu si quieres que te mande el codigo completo mandame un correo para responderte con los ficheros en un .rar y puedas entender mejor lo que te explico.

        Gracias de antemano

      • andrei dice:

        Hola amigo
        Estaba revisando el codigo que te envie pero hay cosas que no salen pudieras enviarme un email para enviarte el codigo tal y como lo tengo?

      • andrei dice:

        Muchas gracias amigo
        Recreando tu ejemplo logre corregir algunos errores que tenia mi codigo, lo que hice fue que los resultados de la busqueda en la base de datos que mando ha hacer a traves de ajax al controlador y a su vez al model los coloco en un view y ese view se colocara en el lugar donde ajax va a colocar su respuesta o resultado es decir en el select.
        Solo que en mi caso no tengo que colocar el index.php ya que uso .htaccess.

        // var url = ‘contratos/clientes’;
        // ajax.open(“POST”, url, true);

        Muchas gracias por tu aporte

  11. Hola
    Como haces o que modificas para que el controlador llamado mediante ajax pueda devolverle a la funcion resp algun valor o variable como resultado de la llamada?
    Osea, en mi controlador ajax tengo una funcion booleana que verifica si el autor tiene o no permiso de acceso.
    Entonces me gustaria en el controlador poder devolver algo de vuelta a la funcion resp y asi informar el error

    Gracias

    • Hola Enrique, para que el controlador pueda responderle a tu función AJAX, es necesario que el controlador “cargue” una vista. Esta vista nunca se mostrará por pantalla, sólo se usa para devolverle a la función AJAX la respuesta. Esta vista puede ser un html, o simplemente código php haciendo “echo”. En tu caso, podrías tener en tu controlador algo así:

      ...
      $is_author = TRUE; //o false, o lo que te devuelva la base de datos, o como sea que averiguas si es autor o no
      $data = array("is_author" => $is_author);
      $this->load->view('respuesta_ajax',$data);
      ...

      En tu vista llamada “respuesta_ajax.php” tendrías este código (y sólo este código):

      if($is_author)
      {
      echo "1";
      }
      else
      {
      echo "0"; // o "No es autor" o lo que quieras responderle a la función AJAX
      }

      De tal forma que tu función javascript “sabe” de antemano qué valores le ha de devolver el controlador, en el ejemplo que te puse, le devolverá 1 si es autor o 0 en caso contrario.
      Espero haber respondido tu pregunta. Si no te queda del todo claro, no dudes en seguir preguntándome!

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s