Vue.js y Ajax

Bueno, hace unos días hice una publicación de Vue.js, donde aprendíamos lo básico para iniciarnos con este framework. Para los que no lo hayan visto y quieran hacerlo aquí:

https://fernando-gaitan.com.ar/introduccion-a-vue-js/

Ahora vamos a continuar, aprendiendo a realizar peticiones http para poder comunicar nuestra aplicación frontend con el backend.

Para eso necesitamos descargarnos el código Vue.js desde el siguiente enlace:

https://vuejs.org/v2/guide/installation.html

Y también tendremos que incluir un complemento que nos permitirá usar el objeto $https:

<script src="https://cdn.jsdelivr.net/vue.resource/1.3.1/vue-resource.min.js"></script>

Podemos incluir el archivo de forma externa, como se muestra en el ejemplo, o bien descargarlo en nuestro proyecto:

https://cdn.jsdelivr.net/vue.resource/1.3.1/vue-resource.min.js

Objeto $http

Podemos revisar las funcionalidades que nos aporta desde su repositorio para profundizar:

https://github.com/pagekit/vue-resource/blob/develop/docs/http.md

Para resumir un poco, la forma de realizar peticiones son de la siguiente manera:

this.$http.get('url', data).then(function(response){
   //Método que se dispara cuando vuelve la respuesta del servidor.
}, function(){
   //Método que se dispara si hubo algún error.
});

A continuación vamos a ver un ejemplo muy sencillo.

Ejemplo

Supongamos que tenemos un lista de personajes de la saga Resident Evil, y a su vez queremos saber en qué juego participó cada personaje. Pero a su vez necesitamos que una vez cargada la lista, al hacer clic en uno de los enlaces del juego, nos rerecargue la lista, pero sólo con los personajes del juego que seleccionamos.

Para ello primero vamos a crear un archivo PHP con el nombre _ajax_response.php y el siguiente código:

<?php
 $request = json_decode(file_get_contents('php://input')); 
 $response = array();
 $personajes = array(
    array('nombre' => 'Ada', 'apellido' => 'Wong', 'juegos' => array(2, 4, 6)), 
    array('nombre' => 'Chris', 'apellido' => 'Redfield', 'juegos' => array(1, 5, 6, 7)),
    array('nombre' => 'Claire', 'apellido' => 'Redfield', 'juegos' => array(2)),
    array('nombre' => 'Ethan', 'apellido' => 'Winters', 'juegos' => array(7)),
    array('nombre' => 'Jill', 'apellido' => 'Valentine', 'juegos' => array(1, 3, 5)),
    array('nombre' => 'Leon', 'apellido' => 'Kennedy', 'juegos' => array(2, 4, 6)),
    array('nombre' => 'Sherry', 'apellido' => 'Birkin', 'juegos' => array(2, 6)) 
 );
 if(is_null($request)){
    $response = $personajes;
 }else{ 
    foreach($personajes as $item){
       if(in_array($request->juego, $item['juegos'])){
          $response[] = $item;
       }
    }
 }
 echo json_encode($response);

Hay que aclarar que la forma de enviar datos es mediante json, por eso no podemos usar en PHP las tradicionales: $_GET, $_POST y $_REQUEST para obtener los datos que vienen del cliente. Sino que en su lugar tendremos que usar algo como esto:

$request = json_decode(file_get_contents(‘php://input’));

Lo que nos devolverá un objeto de PHP, en donde cada atributo va a coincidir con los del json enviado desde el frontend.

Frontend:

data: {
   nombre: 'Cornelio',
   apellido: 'Del Rancho'
};

Backend:

$request = json_decode(file_get_contents('php://input')); 
$nombre = $request->nombre;
$apellido = $request->apellido;

La respuesta será una lista, un array en donde cada posición será un json con este aspecto:

{
   "nombre":"Jill",
   "apellido":"Valentine",
   "juegos":[1,3,5]
}

Bien, ahora podemos continuar con el código, podemos crear un archivo .js, al que yo voy a llamar app.js, con el siguiente código:

var app = new Vue({
   el: '#app',
   data: {
      personajes: []
   },
   created: function(){
         this.$http.get('_ajax_response.php').then(function(response){
         this.personajes = response.body;
      }, function(){
         alert('Error!');
      });
   }
});

Como verán tenemos un atributo array llamado personajes, el cual va a guardar la lista de los personajes de la saga, éste será actualizado en cada petición que hagamos al servidor a _ajax_response.php. Puede traer todos los personajes, o bien los filtrados por juego.

También podemos observar un método que no habíamos visto en la publicación anterior llamado created(), este método se va a disparar una vez que la instancia de Vue se haya realizado. Osea que ni bien se cargue, va a llenar la lista de personajes con ajax.

Usamos .get() para realizar una petición por GET, aunque también podríamos usar .post(), .put(), .delete(), etc.

En cualquiera de los casos, debemos indicar como primer parámetro la url, y como segundo parámetro, de forma opcional, si necesitamos enviar datos. Algo que vamos a hacer después mediante un .post().

this.$http.get('url')

Y finalmente para obtener la respuesta del servidor usamos el método encadenado .then(). El cual va a recibir dos parámetros como callback. El primero se va a disparar cuando el servidor nos haya respondido, mientras que el segundo lo hará si hubo algún error.

.then(function(response){
   console.log('Respuesta del servidor: ' + response);
}, function(){
   console.log('Error');
});

Ahora que ya sabemos esto, podemos continuar mostrando los datos mediante html.

<div class="container">
   <div id="app">
      <h1> Lista de personajes </h1>
      <hr />
      <ul>
         <li v-for="item in personajes"> 
            <h2> {{ item.nombre }} {{ item.apellido }} </h2>
            <div class="row">
               <div class="span2" v-for="item2 in item.juegos">
                  Resident evil {{ item2 }}
               </div>
            </div>
            <hr />
         </li>
      </ul>
   </div>
</div>

Como podemos ver recuperamos la lista de personajes, y recorremos el atributo personajes con un v-for. Luego en cada vuelta tendremos además del atributo nombre y apellido, el atributo juegos, que es un array, y también hacemos un el recorrido de éste. Osea un for dentro de otro for:

<li v-for="item in personajes"> 
   <h2> {{ item.nombre }} {{ item.apellido }} </h2>
   <div class="row">
      <div class="span2" v-for="item2 in item.juegos">
         Resident evil {{ item2 }}
      </div>
   </div>
   <hr />
</li>

Vamos a ver algo con este aspecto:

Ahora para profundizar vamos a hacer algunos cambios a nuestro código, de tal forma que al pulsar en el cada nombre de juego se envíe una petición (esta vez por post), enviando el número del juego, y a cambio nos devuelva la lista de personajes que aparece en el mismo.

Deberíamos cambiar el código javascript por esto:

var app = new Vue({
   el: '#app',
   data: {
      personajes: []
   },
   methods: {
      filtrarPorJuego: function(juego){
         this.$http.post('_ajax_response.php', {
            juego: juego
         }).then(function(response){ 
            this.personajes = response.body;
         }, function(){
            alert('Error!')
         });
      },
      limpiarBusqueda: function(){
         this.$http.get('_ajax_response.php').then(function(response){
            this.personajes = response.body;
         }, function(){
            alert('Error!');
         });
      }
   },
   created: function(){
      this.$http.get('_ajax_response.php').then(function(response){
         this.personajes = response.body;
      }, function(){
         alert('Error!');
      });
   }
});

Aquí ingresamos dos métodos, uno que va a filtrar personajes por juego y otro que va a limpiar la búsqueda, y va a devolver todos los personajes juntos.

Ingresamos el código html:

<div id="app">
   <h1> Lista de personajes </h1>
   <div class="row">
      <div class="span12">
         <a href="javascript:void(0)" v-on:click="limpiarBusqueda()"> Limpiar búsqueda </a>
      </div>
   </div>
   <hr />
   <ul>
      <li v-for="item in personajes"> 
         <h2> {{ item.nombre }} {{ item.apellido }} </h2>
         <div class="row">
            <div class="span2" v-for="item2 in item.juegos">
               <a href="javascript:void(0)" v-on:click="filtrarPorJuego(item2)"> Resident evil {{ item2 }} </a>
            </div>
         </div>
         <hr />
      </li>
   </ul>
</div>

Y quedará algo como esto:

En este caso, hemos filtrado por «Resident evil 1», y sólo nos ha devuelto «Chris Redfield» y «Jill Valentine».

Bueno, a continuación dejo el código en el repositorio para que  puedan verlo:

https://github.com/fernandoggaitan/vuejs_ajax

Saludos!


11 Respuestas a “Vue.js y Ajax”

  1. Buenas comenté hace un rato pero me equivoqué de post, pero en fin, hay un problema con el código y creo que lo que pasa es que cuando hacés this.personajes = response.body lo que le pasa a personajes es un string y no un array de objetos, o por lo menos es lo que pasa en mi caso, si tenés alguna solución estaría muy agradecido, saludos!

  2. Saludos, ¿cómo puedo hacer ese proceso con un método de una clase de PHP y no con un archivo ?

  3. Veo que la función de created y limpiarbusqueda es lo mismo, ¿se puede definir una función aparte y asignarla a ambos?

  4. hola. estoy tratando de seguir el ejemplo para hacer una petición post a una pagina. Yo desarrolle la petición con jquery, pero quiero usar la manera como lo haces. podrías ayudarme?

    $(document).ready(function () {
    $.ajax({
    type: «POST»,
    url: «http://52.200.97.189:8080/parse/functions/LeerTabla»,
    headers: {
    «X-Parse-Application-Id»: «jRMvVrYCjHOERsw»
    },
    success: function (data) {
    console.log(data.result);
    }
    })
    });