una cosita si uds al momento de darle clic a los botones de agregar a Favorito y no les agrega pa´nada, verifiquen que no tengan el End Poin de
limit=2, si no puede acumular una basta cantidad de Michis al momento que lo quiten 😄
Conceptos fundamentales
¿Qué es una API REST?
Flujo de comunicación entre usuarios, frontend y backend
Primeros pasos con fetch
Consume tu primera API REST
Endpoints y query parameters
¿Qué son los HTTP Status Codes?
¿Qué es una API KEY?
Proyecto
Maquetación del proyecto
¿Qué son los Métodos HTTP?
GET: leyendo michis favoritos
POST: guardando michis favoritos
Consultas a la API para escribir HTML dinámico
DELETE: borrando michis favoritos
Headers en peticiones HTTP
¿Qué son los Headers HTTP?
Header de autorización
Header de Content-Type
FormData: publicando imágenes de michis
Bonus
Axios: librerías de JavaScript para consumir APIs
CORS, caché, redirect y tu propio clon de fetch
GraphQL, Web Sockets y Web 3.0: el mundo más allá de REST
Próximos pasos
Toma el Curso Práctico de Consumo de API REST con JavaScript
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Juan David Castro Gallego
Aportes 41
Preguntas 16
una cosita si uds al momento de darle clic a los botones de agregar a Favorito y no les agrega pa´nada, verifiquen que no tengan el End Poin de
limit=2, si no puede acumular una basta cantidad de Michis al momento que lo quiten 😄
Para evitar hardcodear todos los botones, cree listas de los botones, guardo datos entre nodos para leerlos y asi tener funciones mas genericas.
sobre este ciclo coloco los datos sobre el elemento padre entre los atributos.
En esta imagen coloco un evento sobre todos los botones de los michis random, luego en el mismo ciclo determino cual fue el elemento del evento y obtengo de su padre el id del michi a guardar
Para entender mejor el problema del minuto 18:40:
Cuando le asignamos a
btn.onclick = mifuncion()
lo que hacemos es asignarle el resultado de nuestra función; básicamente le estamos diciendo “Te asignaré lo que resulte si ejecutamos mifuncion()”, por eso era que siempre se guardaban en favoritos. Cuando lo envolvemos en una función anónima (cuando haces () => {}, es anónima porque es realmente una función como esta: function mifuncion(){}, solo que sin un nombre) lo que hacemos es que el propio onclick sea una función (que solo se ejecutará cuando sea llamada). De hecho, si luego de hacer lo que JuanDa hizo:
btn.onclick = () => funcion()
hacemos
btn.onclick()
La función se va a ejecutar de igual manera, como si hicieras
btn.onclick = funcion()
Hola, ahí va mi progreso. Lo que hago es agregar caninos dinamicamente y el corazon es para agregarlos a la lista de favoritos
Les comparto otra manera de añadir los michis al DOM!
const API_URL_FAVOTITES = ‘https://api.thecatapi.com/v1/favourites?api_key=c08d415f-dea7-4a38-bb28-7b2188202e46’; para favoritos sin (limit=2) OJO
Amee las reacciones que tiene Juan DC cuando miraba un gatito Jajajaj
Imposible sacarlo de favoritos a ese Michi 😄
Hola, quizás estarás pensando que es un poco tedioso tener que declarar cada imagen con id e igual que los botones si por ejemplo, queremos tener 10 imágenes… Para eso podemos realizar un código parecido al cargar la sección de favorito, con la diferencia que al button le vamos agregar un addEventListener de ‘click’ y hacemos el llamado a la función de salvar en favoritos, para poder pasar el ID de la imagen utilizamos la el método bind
Dejo la imagen de ejemplo, en mi caso estoy con la API de perritos
async function loadRandomDog() {
const response = await fetch(URL_RANDOM)
const data = await response.json();
const randomSection = document.querySelector('#randomDogs');
if(response.status !== 200) {
spanErro.innerHTML = "Hubo un error: " + response.status;
} else {
data.forEach(dog => {
const article = document.createElement('article');
const img = document.createElement('img')
const button = document.createElement('button')
const btnText = document.createTextNode('Guardar en Favoritos')
img.src = dog.url;
button.addEventListener('click', saveFavoritesDog.bind('idDog',dog.id))
button.appendChild(btnText);
article.appendChild(img);
article.appendChild(button);
randomSection.appendChild(article);
});
}
}
Espero que les funcione e igual recibir mejoras para este código
Mi avance…demoré un poco pero me sorprende lo mágico que se puede hacer con solo JavaScript puro…ya quisero aprender REACT ❤
Aclarando las tres formas de insertar texto en un nodo en el DOM. Existen 4 formas de agregar texto:
createTextNode
innerText
innerHTML
textContent
createTextNode
escapará de cualquier cadena y las mostrará tal como son, mientras que innerHTML
podría convertir cadenas similares a html en un DOM. Si no desea eso puede usar textContent
o innerText
que es soportado en IE. Tomar en cuenta también que innerText
es consciente de la apariencia renderizada del texto, mientras que textContent
no lo es.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText
También pueden usar el Try / Catch y con map crear un cliclo, ejemplo-
try{
const michi = await saveMichi();
let view = `
${data.map(michiup => `
<article id="article">
<div>
<img src='${michiup.image.url}'">
</div>
<button class="favorito like"><img src="./dislike-icon.png"></div></button>
</article>
`)}
`;
favoriteMichi.innerHTML = view
} catch(error){
console.log(error)
}
Duré horas tratando de debuggear un error en mi código al agregar nuevas mascotas al favorito, despeje un rato la mente y luego pude solucionarlo 🚀
comparto documentación sobre el parsing
https://developer.mozilla.org/en-US/docs/Glossary/Parse
Les comparto mi progreso
Muy guapa la 2da foto
👉☀️🐈
Esta clase es excelente por todas las posibilidades que te otorga a la hora de jugar con descubrir que puede hacer uno al crear html dinamico. Yo probe una alternativa previo a ver esta clase en la cual en vez de seguir usando el onClick pase a asignarle un eventListener a cada uno de los buttons y quedo de esta forma:
//Realiza un fetch y provee una imagen aleatoria de un gatito, una vez obtenida la asigna al elemento image por medio de su src, ademas usa randomCatName para asignarle un nombre
async function loadRandomMichis() {
const res = await fetch(`${randomAPI}${queryLimit}&${key}${keyAPI}`);
const data = await res.json();
console.log({name: "random",datos: data})
if (res.status !== 200) {
spanError.innerHTML = `Hubo un error ${res.status}`
} else {
// Traemos el container con el que estamos trabajando
const container = document.getElementById('random-cats');
//Generamos nombres aleatorios provenientes de un array para el numero de imagenes con el que estemos trabajando
const title = document.getElementById('cat-title');
let titleContent = "";
for (let i = 1; i <= data.length; i++) {
let catName = randomCatName(catNames);
while (titleContent.includes(catName)) {
catName = randomCatName(catNames);
}
if (i > 1) {
titleContent = titleContent + ", " + catName;
} else {
titleContent = catName;
}
}
// Generamos un array con los nombres asignados a cada imagen
const titleArray = titleContent.split(', ');
//Limpiamos el container entre llamada y llamada
container.innerHTML = '';
// Generamos un article que consta de una imagen y un boton para agregar a favs por cada uno de los michis que importamos
// Asignamos un id dinamico a cada img y cada button por medio de un incrementor en caso que lo necesitemos mas adelante (Css por ej)
let incrementor = 1;
for (element of data) {
const article = document.createElement('article')
const fav_button = document.createElement('button')
fav_button.type = 'button'
fav_button.id = `fav_button-img${incrementor}`
fav_button.className = 'choice-button'
fav_button.innerHTML = 'Save in favs!'
const img = document.createElement('img');
img.id = `img${incrementor}`
img.src = element.url;
img.dataset.id = element.id;
//Basandonos en el nombre que se le asigno en el titulo se lo alojamos en un dataset para enviarlo mas adelante
img.dataset.catName = titleArray[incrementor - 1];
img.width = 300;
img.height = 300;
article.appendChild(img)
article.appendChild(fav_button)
container.appendChild(article)
// Los guardamos en favs enviando tanto su id como el nombre aleatorio que se le brindo en la funcion randomCatName
fav_button.addEventListener('click', () => {
saveFavouriteMichis(img.dataset.id, img.dataset.catName);
});
incrementor++
}
title.innerHTML = titleContent;
}
};
Yo lo hice de esta manera
async function dogsFovurites (subId) {
let favDogs = d.querySelector('#favDogs');
const res = await fetch(`${endpoint.URL_API_FAVOURITES}?sub_id=`+subId)
console.log(res);
const data = await res.json();
try {
let data_nuevo = data.slice(data.length-4);
let datos_fav = `
${data_nuevo.map (dog_fav =>
`
<div class="col mb-3 me-2 ms-3" style="float: left;">
<div class="card " style="width: 18rem;" >
<img src="${dog_fav.image.url}" class="card-img-top img_cambia" alt="..." width="300" height="200">
<div class="card-body">
<button type="button" id="" class="btn btn-primary">${dog_fav.id}</button>
</div>
</div>
</div>
`)}`;
favDogs.innerHTML = datos_fav.replace(/,/g,"")
} catch (error) {
const errorNode = document.querySelector('#error');
errorNode.innerText = `Error: ${error.message}`;
}
}
Yo buscando que esta mal en mi código porque no se agregan los gatitos a favoritos y tenia un end poin limit=4, ahora tengo como 60 favoritos 😮
Una forma que considero mas fácil de insertar código en el html es mediante la función insertAdjacentHTML funciona prácticamente igual que el innerHTML pero sin el eliminar el html que contiene el contenedor.
async function loadRandomMichis() {
const reponse = await fetch(API_URL_RANDOM);
const data = await reponse.json();
const randomMichis_container = document.getElementById("randomMichis_container");
if (reponse.status !== 200) {
console.log("error");
randomMichis_container.innerHTML = `<article>Error ${reponse.status}: ${data.message}</article>`
} else {
randomMichis_container.innerHTML = ""
data.map((cat) => {
randomMichis_container.insertAdjacentHTML("beforeend", `
<article>
<div class="randomMichis_img">
<img src="${cat.url}" class="randomMichis_img" id="img" alt="imagen de los gatos">
</div>
<button id="${cat.id}" type="button"> Guardar en favoritos</button>
</article>`)
const button = document.getElementById(cat.id)
button.addEventListener("click", () => saveFavorite(cat.id))
})
}
}
async function loadFavoritesMichis() {
const response = await fetch(API_URL_FAVORITES);
const data = await response.json();
const favorites = document.getElementById("favorites");
favorites.innerHTML = "";
data.map(favorite => {
favorites.insertAdjacentHTML("beforeend", `
<article class="favorites_container">
<div class="randomMichis_img">
<img src="${favorite.image.url}" class="randomMichis_img" id="img" alt="imagen de los gatos">
</div>
<button type="button">Eliminar de favoritos</button>
</article>
`)
})
}
const fetchData = async (urlApi) => {
const res = await fetch(urlApi);
const data = await res.json();
return {res, data};
};
async function loadRandomDogs(){
const {res, data} = await fetchData(URL_API_RANDOM);
console.log('loadRandomDogs');
console.log (data);
if(res.status !== 200){
const spanError = document.getElementById('error')
spanError.innerHTML = 'Hubo un error ' + res.status;
}else{
const img1 = document.getElementById('img1');
const img2 = document.getElementById('img2');
const img3 = document.getElementById('img3');
const btn1 = document.getElementById('btn1');
const btn2 = document.getElementById('btn2');
const btn3 = document.getElementById('btn3');
img1.src = data[0].url;
img2.src = data[1].url;
img3.src = data[2].url;
btn1.onclick = () => saveFavouriteDog(data[0].id);
btn2.onclick = () => saveFavouriteDog(data[1].id);
btn3.onclick = () => saveFavouriteDog(data[2].id);
}
};
async function loadFavouritesDogs(){
const {res, data} = await fetchData(URL_API_FAVOURITE);
console.log('loadFavouritesDogs')
console.log (data);
if(res.status !== 200){
const spanError = document.getElementById('error')
spanError.innerHTML = 'Hubo un error ' + res.status + res.message;
}else{
data.forEach(dog =>{
const section = document.getElementById('favoriteDogs');
const article = document.createElement('article');
const img = document.createElement('img');
const btn = document.createElement('button');
const btnText = document.createTextNode('Eliminar de favoritos');
img.src = dog.image.url;
btn.appendChild(btnText);
article.appendChild(img);
article.appendChild(btn);
section.appendChild(article);
});
}
};
async function saveFavouriteDog(id){
const { res, data } = await fetch(URL_API_FAVOURITE,{
method: "POST",
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
image_id:id
})
});
console.log('guardar favoritos')
console.log(res);
}
loadRandomDogs();
loadFavouritesDogs();
Lo mejor de esta clase, Juan dándole a favoritos a todos los michis jajajajaja!
usando eventos del body:
main.js
let status;
fetch('https://api.thecatapi.com/v1/images/search?limit=5&api_key=c08d415f-dea7-4a38-bb28-7b2188202e46')
.then(res => {
let miRes = res.json()
status = res.status
return miRes
})
.then(data => {
const IMG = data.map(o => {
console.log(o.id)
const template = document.createElement('template');
template.innerHTML =`
<figure data-url='${o.id}'>
<address>STATUS: ${status}</address>
<img src='${o.url}'/>
<button>guardar</button>
</figure>
`;
return template.content.cloneNode(true)
});
document.querySelector('main').append(...IMG)
})
document.body.addEventListener('click',(e)=> {
if(e.target.textContent == 'guardar'){
let url = e.target.parentNode.dataset.url;
fetch('https://api.thecatapi.com/v1/favourites?api_key=c08d415f-dea7-4a38-bb28-7b2188202e46',{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
image_id: url
})
})
}
})
fetch('https://api.thecatapi.com/v1/favourites?limit=100&api_key=c08d415f-dea7-4a38-bb28-7b2188202e46')
.then(res => res.json())
.then(data => {
const IMG = data.map(o => {
const template = document.createElement('template');
template.innerHTML =`
<figure>
<img src='${o.image.url}'/>
</figure>
`;
return template.content.cloneNode(true)
});
document.querySelector('aside').append(...IMG)
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>API REST</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<style>
figure {
display:grid;
grid-template-rows:max-content 1fr 40px;
}
button{
cursor:pointer
}
button:hover {
background:#111;
opacity:.7;
color:#fff;
}
address {
color:#fff;
}
body{
background:#222;
}
h2{ color: #fff; font-size: 2rem; text-align: center}
img{ width: 100%;height: 200px}
main { border-bottom: 2px solid #fff}
main, aside{
display:grid;
gap: 10px;
grid-template-columns:repeat(auto-fill,minmax(200px,1fr))
}
</style>
<script src="./main.js" defer></script>
</head>
<body>
<h2>cats random</h2>
<main></main>
<h2>cats favorites</h2>
<aside></aside>
</body>
</html>
Esto es lo que he hecho en este curso
https://emazou.github.io/the-cat-api/
asi me senti porque aun no se manipular el DOM
Trabaje con data-attributes en el html para poder tomar los ID
.
html
.
.
Js.
.
<!-- ... -->
<body>
<h1>Cats API App</h1>
<section id="randomCats">
<h2>Random Cats</h2>
<span id="error"></span>
<article>
<img class="cat-image" alt="Foto de gatito 1" style="width:16rem">
<button class="save-action">Save to favorites</button>
</article>
<article>
<img class="cat-image" alt="Foto de gatito 2" style="width:16rem">
<button class="save-action">Save to favorites</button>
</article>
<article>
<img class="cat-image" alt="Foto de gatito 3" style="width:16rem">
<button class="save-action">Save to favorites</button>
</article>
<button onclick="pickACat()">Pick another CAThino</button>
</section>
<section id="favoriteCats">
<h2>favorites Cats</h2>
</section>
<script src="main.js"></script>
</body>
<!-- ... -->
.
JS
const API_URL = "https://api.thecatapi.com/v1";
const API_KEY = "your-api-key";
const endpoints = {
API_URL_LIMIT_SEARCH: (limit = 3) =>
`${API_URL}/images/search?limit=${limit}&api_key=${API_KEY}`,
API_URL_FAVOURITES: `${API_URL}/favourites?api_key=${API_KEY}`,
};
const spanError = document.getElementById("error");
const pickACat = async () => {
const response = await fetch(endpoints.API_URL_LIMIT_SEARCH(3));
try {
const data = await response.json();
const imgTags = document.querySelectorAll(".cat-image");
const btnTags = document.querySelectorAll(".save-action");
imgTags.forEach((element, key) => (element.src = data[key].url));
btnTags.forEach(
(btn, key) => (btn.onclick = () => saveAFavouriteCat(data[key].id))
);
} catch (error) {
if (response.status !== 200)
return (spanError.innerText = "An error has occurred," + data.message);
}
};
const loadFavouriteCats = async () => {
const response = await fetch(endpoints.API_URL_FAVOURITES);
const data = await response.json();
console.log(
"response pick favourites >>>",
response,
data ? data : "no data"
);
data.forEach((cat) => {
const section = document.getElementById("favoriteCats");
const article = document.createElement("article");
const image = document.createElement("img");
const button = document.createElement("button");
const btnText = document.createTextNode("Remove from favourites");
image.src = cat.image.url;
image.style = "width:16rem";
button.appendChild(btnText);
article.appendChild(image);
article.appendChild(button);
section.appendChild(article);
});
};
const saveAFavouriteCat = async (id) => {
const response = await fetch(endpoints.API_URL_FAVOURITES, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
image_id: id,
}),
});
const data = await response.json();
console.log("save", response);
if (response.status !== 200)
return (spanError.innerText = "An error has occurred," + data.message);
};
pickACat();
loadFavouriteCats();
me estoy haciendo el de perriotos 😉
console.log("estamos listos");
const key = '93281cee-4d7f-4c6d-abc9-62cc90323eb1';
const API_URL_RANDOM = "https://api.thedogapi.com/v1/images/search?limit=6&api_key="+key;
const API_URL_FAVORITES = "https://api.thedogapi.com/v1/favourites";
const getRandomImage = async() => {
const res = await fetch(API_URL_RANDOM);
const data = await res.json();
console.log("get Image")
console.log(data);
if(res.status !== 200){
console.log("Error: "+ res.status);
}else {
const img1= document.getElementById('img1');
const img2= document.getElementById('img2');
const img3= document.getElementById('img3');
const img4= document.getElementById('img4');
const img5= document.getElementById('img5');
const img6= document.getElementById('img6');
img1.src = data[0].url
img2.src = data[1].url
img3.src = data[2].url
img4.src = data[3].url
img5.src = data[4].url
img6.src = data[5].url
};
};
const getImagesFavorites = async() => {
const res = await fetch(API_URL_FAVORITES, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'x-api-key': '93281cee-4d7f-4c6d-abc9-62cc90323eb1'
},
});
const data = await res.json();
console.log("get Favorites")
console.log(data);
if(res.status !== 200){
console.log("Error: "+ res.status +" "+ data.message);
}
};
const saveImageFavorites = async (value) => {
const res = await fetch(API_URL_FAVORITES, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': '93281cee-4d7f-4c6d-abc9-62cc90323eb1',
},
body: JSON.stringify({
"image_id": "UyN27ZccR",
}),
});
const data = await res.json();
console.log('save');
console.log(res);
console.log("cambiando el color"+value);
const element = document.getElementById('start'+value);
element.classList.toggle('start-active');
if(res.status !== 200){
console.log("Error: "+ res.status +" "+ data.message)
}
};
const another =() => {
getImage();
};
getRandomImage();
getImagesFavorites();
Quiero aportar el código de la clase, pero usando POO y escribiendolo en TypeScript 😄. Posdata: La función loadRandomMichis del profe la separé en dos funciones una que se dedique al DOM de favoriteImages y la otra se encarga de hacer el fetch y obtener la data. Lo hice con el objetivo de seguir el concepto de one job only.
import { Cat } from "./../models/cat.model";
import { RequestFailed } from "./../models/request.failed.model";
import { FavoriteCat } from "./../models/favorite.cat.model";
export class LoadCatImage {
constructor (
private readonly apiUrlRandom: string,
private readonly apiUrlFavorites: string,
private readonly elementImages: HTMLCollectionOf<Element>,
private readonly spanError: HTMLElement | null,
private readonly saveFavorite1: HTMLElement | null,
private readonly saveFavorite2: HTMLElement | null,
) {
this.randomImages = this.randomImages.bind(this);
this.saveOnFavorites = this.saveOnFavorites.bind(this);
this.favoriteImages = this.favoriteImages.bind(this);
}
private favoriteImagesDom (data: FavoriteCat[]): void {
const section: HTMLElement | null = document.getElementById("favoriteCats");
data.forEach(cat => {
const article: HTMLElement = document.createElement("article");
const imageElement: HTMLElement = document.createElement("img");
const button: HTMLElement = document.createElement("button");
const image: HTMLImageElement = imageElement as HTMLImageElement;
const buttonText: Text = document.createTextNode("Get out cat picture from favorites");
button.appendChild(buttonText); //Se le agrega un texto al botón
article.appendChild(image);
article.appendChild(button);
if (section !== null) {
section.appendChild(article);
}
image.src = cat.image.url;
image.width = 150;
});
}
async favoriteImages (): Promise<void> {
const res: Response | null = await fetch(this.apiUrlFavorites);
if (res.status === 200) {
const data: FavoriteCat[]= await res.json();
this.favoriteImagesDom(data);
} else {
this.catchError(res);
}
}
async randomImages ():Promise<void> {
const res: Response | null = await fetch(this.apiUrlRandom);
if (res.status === 200) {
const data: Cat[]= await res.json();
this.handleEventFavoriteButton(data);
// this.images = [];
for (let index = 0; index < this.elementImages.length; index++) {
const image = this.elementImages[index] as HTMLImageElement;
image.src = data[index].url;
}
} else {
this.catchError(res);
}
}
private async catchError(res: Response | null): Promise<void> {
if (this.spanError !== null && res !== null) {
const dataError: RequestFailed = await res.json();
this.spanError.innerText = `Something went wrong. Error ${dataError.status}. ${dataError.message}`;
}
}
private handleEventFavoriteButton (favorites: Cat[]): void {
if (this.saveFavorite1 !== null && this.saveFavorite2 !== null) {
this.saveFavorite1.onclick = () => this.saveOnFavorites(favorites[0]);
this.saveFavorite2.onclick = () => this.saveOnFavorites(favorites[1]);
}
}
async saveOnFavorites (favorite: Cat): Promise<void> {
let idImage: string = favorite.id;
const res: Response | null = await fetch(this.apiUrlFavorites, { //Cuando se quiere hacer una peticion
//con fetch que no sea get se debe colocar las indicaciones de la peticion.
method: "POST",
headers: {
"Content-Type": "application/json" //Lo indica la api.
},
body: JSON.stringify({
image_id: idImage
})
});
if (res.status === 200) {
console.log(res);
} else {
this.catchError(res);
}
}
}
Este es mi aporte jaja 😄
<code>
const d = document,
$fragment = d.createDocumentFragment();
const api_url_random = 'https://api.thecatapi.com/v1/images/search?limit=10&',
api_url_favorites = 'https://api.thecatapi.com/v1/favourites',
api_key = "e06a0153-5e69-4361-a4da-37f0698786d4";
const createMichi = (data, contentBtn) => {
const $container = d.createElement('article'),
$image = d.createElement('img'),
$btnAdd = d.createElement('button');
$container.classList.add('michi-random');
$image.src = data.url || data.image.url;
$image.alt = "Michi random";
$image.id = data.id;
if(contentBtn === "Eliminar michi de favoritos"){
$btnAdd.classList.add("btn-delete");
}else{
$btnAdd.classList.add("btn-add");
}
$btnAdd.dataset.id = data.id;
$btnAdd.textContent = contentBtn;
$container.append($image, $btnAdd);
return $container;
};
const getData = async (url) =>{
try{
let res = await fetch(url),
data = await res.json();
data.forEach(el => {
const $michi = createMichi(el, "Agregar michi a favoritos");
$fragment.append($michi);
});
d.querySelector('#randomMichis').innerHTML = '';
d.querySelector('#randomMichis').append($fragment);
}catch(err){
console.error(err);
}
}
const getFavorites = async (url) => {
try{
let res = await fetch(url),
data = await res.json();
if(!data[0]){
d.querySelector('#favoritesMichis').innerHTML = `
<h3 style="color: red; font-size: 2.2rem; text-align: center;">No hay michis D:</h3>
`;
}else{
console.log(data);
data.forEach(el => {
const $michi = createMichi(el, "Eliminar michi de favoritos");
console.log(el)
$fragment.append($michi);
});
console.log($fragment);
d.querySelector('#favoritesMichis').innerHTML = '';
d.querySelector('#favoritesMichis').append($fragment);
}
}catch(err){
console.error(err);
}
}
const saveFavoriteMichi = async(url, id) => {
try{
let res = await fetch(url,{
method: 'POST',
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({
image_id: String(id),
})
})
getFavorites(`${api_url_favorites}?api_key=${api_key}`);
console.log(res);
}catch(err){
}
}
const deleteMichi = async (url) =>{
try{
let res = await fetch(url,{
headers: { "x-api-key": api_key },
method: "DELETE",
})
}catch(err){
}
}
d.addEventListener('DOMContentLoaded', e => {
getData(`${api_url_random}?api_key=${api_key}`);
getFavorites(`${api_url_favorites}?api_key=${api_key}`);
});
d.addEventListener('click', e => {
if(e.target.matches('.btn-reload')){
getData(`${api_url_random}?api_key=${api_key}`);
}
if(e.target.matches('.btn-add')){
let id = e.target.dataset.id;
saveFavoriteMichi(`${api_url_favorites}?api_key=${api_key}`, id);
}
if(e.target.matches('.btn-delete')){
let id = e.target.dataset.id,
item = e.target;
deleteMichi(`${api_url_favorites}/${id}`);
item.parentNode.remove()
}
})
Yo lo hice de esta forma
data.forEach((itemCat) => {
console.log(itemCat);
containerFavourites.insertAdjacentHTML(
'beforeend',
`
<article>
<img id=${itemCat.id} class="img-cat_favorite" width="300" height="300" alt="Foto gato aleatorio" src=${itemCat.image.url} />
<button class='button_delete-favourite' >Eliminar foto de favoritos</button>
</article>
`
);
});
}
Intenté hacerlo con templates, pero solo mostraba a un solo elemento del array de favoritos y al último:
JAJAJAJ
ME dio mucha risa en el minuto 19:15 donde sale un señor arrastrando un gato
y el profesor dice:
un gatito que no quiere caminar
CRC === SRC
Hola! Yo hice el append de esta manera:
console.log(API_URL)
const res = await fetch(API_URL)
const data = await res.json()
const section = document.getElementById("section")
//pruba de limitacion de el array.
let ari = data.splice(0,3)
const htmlElement = ari.forEach( item => {
const article = document.createElement("article")
const img = document.createElement("img")
img.src = item.url
img.id = item.id
const btn = document.createElement("button")
btn.onclick = () => saveFavoriteCat(item.id)
const btnText = document.createTextNode("Agregar a favoritos")
btn.appendChild(btnText)
article.appendChild(img)
article.appendChild(btn)
section.appendChild(article)
})
Así va mi código por ahora, estoy usando try y catch, para las funciones, así como manipulación del DOM desde JS.
Este es el HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="src/styles.css">
<title>Gatitos Aleatorios</title>
</head>
<body>
<h1>Michis App</h1>
<button id="refresh-button">Actualizar</button>
<h2>Gatitos Aleatorios</h2>
<section id="randomCats">
</section>
<h2>Gatitos Favoritos</h2>
<section id="favoritesMichis">
</section>
<script src="src/reto1.js"></script>
</body>
</html>
Y EL JS
const refreshButton = document.querySelector('#refresh-button')
const API_URL = 'https://api.thecatapi.com/v1/'
const API_KEY= 'api_key=live_Bb5fxkkALOgv5l6bnPVukl9NVfwQjy1v1FkbLITMDHRMzZRUT3BlTbY7Lbh1LaAl'
const spanError = document.querySelector('#error')
const buttons = document.querySelectorAll('button')
let HTTPStatus=[
{
number: 200,
link: 'https://t4.ftcdn.net/jpg/05/34/44/37/240_F_534443710_dLVbUS1MtquWRhdWQ0a1iN3M5aZpyLOq.jpg',
},
{
number: 201,
link: 'https://t4.ftcdn.net/jpg/01/01/50/43/240_F_101504362_Y9uq3U32d3JdmyeWGFzU5aNCwUiLzkoO.jpg',
},
{
number: 203,
link: 'https://www.onlinesolutionsgroup.de/wp-content/uploads/203-Non-Authoritative-Information-1000x600.jpg',
},
{
number: 300,
link: 'https://www.onlinesolutionsgroup.de/wp-content/uploads/statuscode-300-multiple-choices-1.jpg',
},
{
number: 307,
link: 'https://t4.ftcdn.net/jpg/02/38/85/91/240_F_238859191_dXYTC8lTaJ3nBpEYYI6UNaRjd3vTDNUh.jpg',
},
{
number: 400,
link: 'https://as1.ftcdn.net/v2/jpg/01/35/88/24/1000_F_135882447_SeFbWwnJ7Ig5ZQ9mpG22NHBhs6L2fBVy.jpg',
},
{
number: 401,
link: 'https://as1.ftcdn.net/v2/jpg/01/35/88/24/1000_F_135882440_5epLvLQRBM42f90SD8yyKQIPno03j5Ef.jpg',
},
{
number: 403,
link: 'https://www.seokratie.de/wp-content/uploads/2022/06/AdobeStock_135882455-751x501.jpeg',
},
{
number: 404,
link: 'https://www.onlinemarketingmonkey.be/wp-content/uploads/2022/05/Uitgelicht-404.jpg',
},
{
number: 500,
link: 'https://as1.ftcdn.net/v2/jpg/01/35/88/24/1000_F_135882460_jMCfN05mhPOm2C8MvqvYym0e4qj5cKAC.jpg',
},
{
number: 503,
link: 'https://as2.ftcdn.net/v2/jpg/03/61/45/09/1000_F_361450985_YulVwRLEJmn7S5cOVITufWX1czh9lGKA.jpg',
},
{
number: 504,
link: 'https://t3.ftcdn.net/jpg/00/91/06/04/240_F_91060405_sqGYr6VG208sMURrSdSlPcay3ds1mlyV.jpg',
},
]
refreshButton.addEventListener('click', () => {
location.reload();
})
async function fetchData(urlApi) {
const response = await fetch(urlApi);
const status = response.status
if(status !== 200){
const resp = HTTPStatus.find(item => item.number === status)
const imgStatus = document.createElement('img')
imgStatus.className = 'imgStatus'
imgStatus.src = resp.link
spanError.appendChild(imgStatus);
console.log('error')
} else{
const data = await response.json();
return data
}
}
const loadImg = async (urlApi) => {
try {
const data = await fetchData(`${urlApi}images/search?limit=3&${API_KEY}`);
console.log(data, 'data')
const allImg = [];
data.forEach(item => {
const image =document.createElement('img');
image.src = item.url
id = item.id
const iconFavorite = document.createElement('img')
iconFavorite.src = 'https://img.icons8.com/external-those-icons-lineal-color-those-icons/512/external-favorite-bookmarks-tags-those-icons-lineal-color-those-icons.png'
iconFavorite.className = 'icon'
const buttonFavorites = document.createElement('button')
buttonFavorites.className = 'buttonFavorites'
buttonFavorites.appendChild(iconFavorite)
const card = document.createElement('article')
card.append(image, buttonFavorites)
allImg.push(card)
buttonFavorites.addEventListener('click', () => saveFavouriteCats(API_URL, id))
});
const sectionRandomCats = document.querySelector('#randomCats')
sectionRandomCats.append(...allImg)
}
catch(error){
console.error(error)
}
};
const loadFavouritesImg = async (urlApi) => {
try {
const data = await fetchData(`${urlApi}favourites?${API_KEY}`,);
console.log(data, 'favorites data')
const allimg = [];
data.forEach(item => {
const image =document.createElement('img');
image.src = item.image.url
const iconDeleteFavorite = document.createElement('img')
iconDeleteFavorite.src = 'https://img.icons8.com/external-those-icons-lineal-color-those-icons/512/external-favorite-bookmarks-tags-those-icons-lineal-color-those-icons-2.png'
iconDeleteFavorite.className = 'icon'
const buttonDeleteFavorite = document.createElement('button')
buttonDeleteFavorite.className = 'buttonFavorites'
buttonDeleteFavorite.appendChild(iconDeleteFavorite)
const card = document.createElement('article')
card.append(image, buttonDeleteFavorite)
allimg.push(card)
console.log(allimg)
const sectionRandomCats = document.querySelector('#favoritesMichis')
sectionRandomCats.append(...allimg)
// buttonDeleteFavorite.addEventListener('click', () => {
// // deleteFavouriteCat(API_URL);
// })
});
}
catch(error){
console.error(error)
}
};
const saveFavouriteCats = async (urlApi, idImg) => {
console.log(idImg, 'ids antes del try en save')
try {
const res = await fetch(`${urlApi}favourites?${API_KEY}`,{
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
image_id: idImg
}),
});
console.log('SaveCats', res)
}
catch(error){
console.error(error)
}
}
loadImg(API_URL);
loadFavouritesImg(API_URL);
Asi va mi página 😄:
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?