Daniel Fenoll
Daniel Fenoll

Reputation: 1

Can't Fetch data - JavaScript async function from jsonplaceholder

DOM does not render the info I pick from the API jsonplaceholder. Just want to render some authors and abstracts.

This is my HTML code, and JS:

<!DOCTYPE html>
<html lang="es">
<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">
<title>Blog - Lista de Comentarios</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.flex {
display: flex;
flex-wrap: wrap;
}
.flex article {
width: calc(50% - 20px);
margin: 10px;
padding: 10px;
border: 2px solid black;
}
.flex article:nth-child(even)
{
background-color: #f0f0f0;
}
select {
border: 2px solid tomato;
width: 80%;
padding: 20px;
margin: 20px auto 0px auto;
display: block;
font-size: 150%;
}
hr {
margin: 20px;
}
</style>
</head>
<body>
<header>
<select id="selectAutor">
<option value="" selected>Selecciona un autor</option>
<option value="1">Autor 1</option>
<option value="2">Autor 2</option>
<option value="3">Autor 3</option>
<!-- Añadir más opciones según sea necesario -->
</select>
<hr>
</header>
<section id="comentarios" class="flex">
<!-- esta es la superficie iterable que hay que repetir por cada comentario -->
<article>
<h3>Nombre del autor</h3>
<p>Email: [email protected]</p>
<p>Comentario:</p>
<p>Texto del comentario</p>
</article>
</section>
<script src="script.js"></script>
</body>
</html>
document.addEventListener('DOMContentLoaded', () => {


// Función para obtener los comentarios de la API REST
async function obtenerComentarios() {
  const url = '...URL...jsonplaceholder...';
  
  try {
    const response = await fetch(url);
    const comentarios = await response.json();
    return comentarios;
  } catch (error) {
    console.error('Error al obtener los comentarios:', error);
    throw new Error('Error al obtener los comentarios');
  }
}

// Función para mostrar los comentarios de un autor seleccionado
async function mostrarComentariosPorAutor(idAutor) {
  console.log('ID del autor seleccionado:', idAutor);
  try {
    // Obtener todos los comentarios
    const comentarios = await obtenerComentarios();
    console.log('Comentarios obtenidos:', comentarios);
    // Filtrar los comentarios del autor seleccionado
    const comentariosAutor = comentarios.filter(comentario => comentario.userId == idAutor);
    console.log('Comentarios del autor seleccionado:', comentariosAutor);

    // Seleccionar el contenedor de comentarios en el DOM
    const contenedorComentarios = document.getElementById('comentarios');
    contenedorComentarios.innerHTML = '';

    // Mostrar cada comentario del autor seleccionado en el DOM
    comentariosAutor.forEach(comentario => {
      const article = document.createElement('article');
      article.innerHTML = `
        <h3>Nombre del autor: ${comentario.name}</h3>
        <p>Email: ${comentario.email}</p>
        <p>Comentario:</p>
        <p>${comentario.body}</p>
      `;
      contenedorComentarios.appendChild(article);
    });
  } catch (error) {
    console.error('Error al mostrar los comentarios:', error);
  }
}

// Manejar el evento de cambio en el selector de autor
document.getElementById('selectAutor').addEventListener('change', event => {
    console.log('Evento de cambio detectado');
  const idAutor = parseInt(event.target.value);
  console.log('ID del autor seleccionado:', idAutor);
  if (idAutor) {
    mostrarComentariosPorAutor(idAutor);
  }
});

});

Upvotes: 0

Views: 217

Answers (2)

Carsten Massmann
Carsten Massmann

Reputation: 28206

I assume that OP was referring to the resource https://jsonplaceholder.typicode.com and therefore I prepared the following snippet to collect comments to posts a certain user (=author) has committed.

Maybe this is was OP wanted? In any case, there are a few patterns in here that might be helpful otherwise.

// if you place this script tag UNDER your body 
// you will not need to use the DOMContentLoaded event
// and you can set up some global constants
const [autsel, cmtdisp] = ["selectAutor", "comentarios"].map(id => document.getElementById(id));

// asynchrounous IIFE: we are doing all the asynchronous stuff in here
(async function() {
  const url = 'https://jsonplaceholder.typicode.com/';

  try {
    // get users and comments:
    const [users, comments] = await Promise.all(["users", "comments"].map(v => fetch(url + v).then(r => r.json())));
    // comments are related to postIds and these are related to users (authors)
    // if you want to have comments per author your would need a two step lookup process.
    // Luckily the data in JSON placeholder follows a simple pattern: 
    // userId = 1+Math.floor((postId-1)/10)
    // We can use this to reorganize our comments:
    const cmts = comments.reduce((a, c) => {
      (a[1 + Math.floor((c.postId - 1) / 10)] ??= []).push(c);
      return a;
    }, {});
    autsel.innerHTML = users.map(u => `<option value="${u.id}">${u.name}</option>`).join("");
    autsel.addEventListener("change", showComments(cmts));
    showComments(cmts)({target:{value:1}}) // show comments for first author ...
  } catch (error) {
    console.error('Error getting users and comments:', error);
    throw new Error('Error getting users and comments');
  }
})();

function showComments(cmtsObj) {
  return function(ev) {
    const id = ev.target.value;
    cmtdisp.innerHTML = cmtsObj[id].map(c => `<article>
<h3>${c.name}</h3>
<p>Email: ${c.email}</p>
<p>Comentario:</p>
<p>${c.body}</p>
</article>`).join("\n")
  }
}
article {
  margin: 4px;
  padding: 4px;
  border: solid grey 1px
}
<header>
  <select id="selectAutor">
  </select>
  <hr>
</header>
<section id="comentarios" class="flex">
</section>

Upvotes: 0

Silas
Silas

Reputation: 1

I translated your code to english and added some demo JSON. it works:

https://jsfiddle.net/gtpo4j3m/

so I guess you should check your JSON response by doing something like:

const response = await fetch(url);
const comentarios = await response.json();
console.log('comentarios', comentarios);

The response should be similar to the getComments() function in the jsfiddle. What does it say?

Upvotes: 0

Related Questions