Blog post image

Parte 2: Aprende a consumir API’s creando un proyecto en VueJS

AuthorGenesis Rivera Rios
Date
8/24/2020
Time8 min read

Continuación

Vamos a empezar a trabajar en el componente del mapa.

En el post anterior creamos los archivos de los componentes y empezamos a trabajar en el componente del input en el cual manejamos eventos.

Ahora vamos a instalar la librería de leaflet para poder eñsenarle al usuario un mapa con la información de su búsqueda.

leaflet

Si entramos a la documentación de leaflet podremos ver las instrucciones de instalación, en este caso estaré utilizando el CDN que nos instruye la documentación.

Así que vamos a buscar el directorio llamado public y abrimos el archivo llamado index.html en el cual estaremos añadiendo las líneas de código.

Vamos a buscar el HTML tag llamado head y a lo ultimo añadimos la referencia al CSS de leaflet

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" />

Luego vamos al tag de body y a lo ultimo añadimos

<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"></script>

Ahora ya que tenemos las referencias debidas para comenzar a utilizar leaflet vamos a añadir nuestro mapa.

Mapa

Ahora, en el componente de Map.vue vamos a añadir adentro del tag llamado template un div con el id de “map”.

<div id="map"></div>

Luego en el área de style le asignamos un valor de altura.

#map { height: 600px; }

Primero vamos a crear la función de data en nuestro componente y crear tres propiedades una llamada map, otra llamada apiResults y la ultima llamada marker.

data () {
  return {
    map: null,
    apiResults: null,
    marker: null
  }
},

Luego creamos un método nuevo adentro del bloque de código de methods llamado prepareMap

methods: {
  prepareMap: function () {
  }
},

Ahora vamos a asignarle valor a la propiedad reactiva llamada map en la cual vamos a dejarle saber a leaflet cual es el elemento en nuestro HTML que contiene el mapa por eso vemos en el código la palabra L.map(‘map’).

Luego en mainlayer vamos a poner la información de open street map para las imágenes que el mapa utilizara para enseñarnos las calles y áreas del mundo

this.map = L.map('map').setView([18.2388, -66.0352], 13);
let mainlayer = L.tileLayer(
	'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
	{
		maxZoom: 18,
		attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>, &copy; <a href="https://carto.com/attribution">CARTO</a>',
	}
);
mainlayer.addTo(this.map);

Si al tratar de ejecutar tu aplicación salen errores puedes utilizar la siguiente línea en el método de prepareMap para ignorar los errores que nos enseña el ESLinter.

/* eslint-disable */

En este caso nos enseña errores ya que estamos utilizando la variable L la cual EsLinter identifica como variable no declarada. Pero en realidad esa variable es parte de la librería de leaflet.

Ahora que tenemos nuestro mapa en su lugar vamos a comenzar a manejar los eventos que emite el componente de SearchInput.

Adentro del área de script en export default vamos a añadir estas siguientes líneas.

  created (){
    bus.$on('user-input', (userInput) => {
      this.getCountryInformation(userInput);
    })
  },
  methods: {
    getCountryInformation: function (userInput) {

    }
  }

Las líneas que están adentro de created() se encargan de dejarle saber a nuestro component que cuando el evento llamado ‘user-input’ se ejecute que el método llamado getCountryInfomation será invocado y se le pasara el valor que el usuario entro. O sea que el método llamado getCountryInformation se va a encargar de hacer nuestra llamada al API.

API

Ahora comenzaremos a escribir nuestra llamada al API. La llamada que estaremos haciéndole al API será un “Get Request” así que nadamas le estaremos pidiendo información.

Normalmente para hacer llamadas a API’s se instalan librerías externas como Axios o JQuery pero en este tutorial estaremos utilizando un API nativo de la mayoría de los buscadores web modernos llamada Fetch API

En el bloque de código del método getCountryInformation escribiremos las líneas de código a continuación.

    getCountryInformation: function (userInput) {
      fetch(`https://restcountries.eu/rest/v2/name/${userInput}`)
      .then(response => response.json())
      .then(data => console.log(data));
	}

Ahora cómo podemos ver en nuestro código estamos utilizando el fetch API con un URL del dominio restcountries el cual recibe un nombre de un país. Cuando recibe el nombre del país nos devuelve la información del país.

Como pueden ver por ahora no estamos haciendo nada con la información que recibimos, solamente la escribimos a la consola.

Les recuerdo que es mala práctica recibir información entrada por el usuario sin hacer verificaciones pertinentes antes de utilizarla ya que hace nuestro sistema vulnerable a ataques.

Ahora si miramos la consola de nuestro buscador web podremos ver nuestro objeto tipo JSON con la información que el API nos devolvió.

En este ejemplo escribí 'Puerto' en el componente de búsqueda y le di click al botón de búsqueda a la derecha.

JSON response

Ahora podemos comenzar a utilizar esta información que recibimos, primero vamos a guardarla en la variable de apiResults.

Así que vamos a volver a el método de getCountryInformation y cambiemos el console.log

Como podemos ver en este bloque de código añadí una variable llamada self la cual guardara el contexto de ejecución y luego utilizo el valor de esa variable para utilizar la variable de apiResults y asignarle el valor del resultado que nos devuelve el API.

getCountryInformation: function (userInput) {
  let self = this;
  fetch(`https://restcountries.eu/rest/v2/name/${userInput}`)
  .then(response => response.json())
  .then(data => self.apiResults = data[0]);
},

Watch

Ahora vamos a comenzar a utilizar esos datos que nos están llegando del API, por ahora no voy a manejar errores en la llamada que estamos haciendo.

Así que vamos a crear un Watch en nuestro componente de vue, esto se va a encargar de que en el momento que cambie la propiedad que le especifiquemos al watcher podamos tomar algún tipo de acción, hacer algo.

Para crearlo escribimos la siguientes líneas de código después de nuestro methods

watch : {

  }

Ahora lo que nos falta hacer es que cada vez que los datos del resultado (la variable apiResults) cambien, vamos a poner un marcador azul en el mapa indicativo del área y vamos a mostrar información relevante al nombre del área que el usuario escribió, la información la eñsenaremos utilizando unos controles de HTML nativos a leaflet.

Ahora adentro de nuestro watch vamos a añadir la propiedad de apiResults. En la propiedad de apiResults adentro de watch vamos a crear una variable con las coordenadas y vamos a invocar el método que añade el marcador a nuestro mapa.

watch : {
  apiResults () {
    let coordinates = this.apiResults.latlng;
    this.markCoordinates(coordinates);
  }
}

Entonces comencemos con el marcador en el mapa, vamos a crear un método llamado markCoordinates

El método de markCoordinates se va a encargar de recibir un parámetro con las coordenadas del área y utilizando esas coordenadas va a añadir un marcador al mapa y va a llevarnos utilizando una animación hacia el marcador, tambien si existe algun marcador ya puesto en nuestro mapa lo va a remover antes de añadir uno nuevo.

En la línea de this.map.flyTo el segundo parámetro que recibe esa función se encarga del nivel de 'zoom' que le queramos dar a nuestro mapa.

markCoordinates: function (coordinates) {
  if(this.marker)
    this.map.removeLayer(this.marker);
  this.marker = L.marker(coordinates).addTo(this.map);
  this.map.flyTo(coordinates, 10);
},

Ahora vamos a añadir la información relevante que nos devuelve el API a un control para mostrársela al usuario.

Vamos a crear un método llamado mapInformationControl.

Este método primero va a verificar si el elemento de HTML que vamos a crear con la información que se le mostrara al usuario ya existe. Así que las primeras tres líneas se encargaran de esa parte. El elemento que vamos a crear va a tener un id de ‘leaflet-information-box’ así que vamos a buscar ese elemento utilizando document.getElementById. let element = document.getElementById('leaflet-information-box');

Ahora que tenemos ese elemento en nuestra variable vamos a verificar si existe o no. Si el elemento existe lo vamos a remover del DOM.

if(element)
        element.parentNode.removeChild(element);

Ok, ahora vamos a comenzar a dibujar nuestra caja de información. Primero voy a crear una variable con el valor de nuestro contexto de ejecución.

let self = this

Luego voy a comenzar a crear el control de leaflet.

let informationBox = L.control({position: 'bottomleft'});

Como podemos ver en esa línea de código estamos posicionando la caja en la parte izquierda abajo.

Luego voy a crear otra variable nombrada div la cual va a crear el elemento HTML.

let div = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom');

Ahora voy a añadirle estilo a nuestro div.

Estas próximas líneas de código, primero le ponen un id al elemento, el cual utilizamos anteriormente para identificar la caja de información. Luego le asignamos el color de fondo, el ancho, relleno y overflow por si el texto es largo.

      div.id = 'leaflet-information-box'
      div.style.backgroundColor = 'white';
      div.style.width = '100%';
      div.style.paddingTop = '10px';
      div.style.paddingLeft = '7px';
      div.style.height = '400px';
      div.style.overflow = 'auto';

Ahora vamos a comenzar a utilizar la información que estamos recibiendo del api. Primero vamos a mostrar el nombre del país. Como vimos en nuestro JSON anteriormente la propiedad que contiene el nombre del país es llamada name así que this.apiResults.name hace referencia a ese nombre, igual que en las próximas líneas de código que hacemos referencia a otras propiedades que estaremos mostrando.

div.innerHTML += `<h5>Informacion sobre: ${this.apiResults.name}</h5>`;
div.innerHTML += '<br>'
div.innerHTML += `<p>Capital: ${this.apiResults.capital}</p>`
div.innerHTML += `<p>Sub Region: ${this.apiResults.subregion}</p>`
div.innerHTML += `<p>Moneda: ${this.apiResults.currencies[0].name} ${this.apiResults.currencies[0].symbol}</p>`
div.innerHTML += `<img class="fluid" style="height:90px;width:90px;" src="${this.apiResults.flag}" alt="Country flag"></img>`

Vamos a añadir el elemento a nuestro mapa.

informationBox.onAdd = function (map) {
  return div;
}   
informationBox.addTo(this.map);

Código completo de esa área.

mapInformationControl: function () {
  let element = document.getElementById('leaflet-information-box');
  if(element)
    element.parentNode.removeChild(element);
  let self = this;
  let informationBox = L.control({position: 'bottomleft'});
  let div = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom');
  div.id = 'leaflet-information-box'
  div.style.backgroundColor = 'white';
  div.style.width = '100%';
  div.style.paddingTop = '10px';
  div.style.paddingLeft = '7px';
  div.style.height = '400px';
  div.style.overflow = 'auto';
  div.innerHTML += `<h5>Informacion sobre: ${this.apiResults.name}</h5>`;
  div.innerHTML += '<br>'
  div.innerHTML += `<p>Capital: ${this.apiResults.capital}</p>`
  div.innerHTML += `<p>Sub Region: ${this.apiResults.subregion}</p>`
  div.innerHTML += `<p>Moneda: ${this.apiResults.currencies[0].name} ${this.apiResults.currencies[0].symbol}</p>`
  div.innerHTML += `<img class="fluid" style="height:90px;width:90px;" src="${this.apiResults.flag}" alt="Country flag"></img>`
  informationBox.onAdd = function (map) {
    return div;
  }   
  informationBox.addTo(this.map);
}

Por último tenemos que invocar nuestro nuevo método en el watch.

watch : {
  apiResults () {
    let coordinates = this.apiResults.latlng;
    this.markCoordinates(coordinates);
    this.mapInformationControl();
  }

Ahora si ejecutamos en nuestro command line en el directorio de rest-countries el comando de npm run serve, podremos ver nuestro proyecto.

Todo el source code se encuentra en un repositorio de github.

Categoria: vuejs