Cant access get results from fetch api request - javascript

I've been trying to access the array results from my fetch api request. I can get the results to return and parse it from json into a javascript object. However I cant access the results. The array is that is return called results. I wondering what I'm missing. The ultimate aim of the project is to get 12 random profiles from the api and get it to display to the card div. The error message I'm getting is 'Uncaught (in promise) TypeError: Cannot read property 'results' of undefined at app.js:40'
HTML
<!DOCTYPE html>
<html lang="en-US">
<head>
<title>Public API Requests</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link href="css/normalize.css" rel="stylesheet">
<link href="css/styles.css" rel="stylesheet">
</head>
<body>
<header>
<div class="header-inner-container">
<div class="header-text-container">
<h1>AWESOME STARTUP EMPLOYEE DIRECTORY</h1>
</div>
<div class="search-container">
</div>
</div>
</header>
<div id="gallery" class="gallery">
</div>
</body>
<script type="text/javascript" src="app.js"></script>
</html>
Javascript
const gallery = document.getElementById('gallery');
const card = document.createElement('div');
card.classList.add('card');
gallery.appendChild(card);
function fetchData(url) {
return fetch(url)
.then(response => { return response.json()})
.then(data => {console.log(data)})
.catch(error => {console.log('Error with fetching API', error)})
}
function generateInfo(data) {
const info = data.map( item => `
<div class="card-img-container">
<img class="card-img" src="${data}" alt="profile picture">
</div>
<div class="card-info-container">
<h3 id="name" class="card-name cap">${name.first} ${name.last}</h3>
<p class="card-text">${data.email}</p>
<p class="card-text cap">${location.city}</p>
</div>
`)
card.innerHTML = info;
}
fetchData('https://randomuser.me/api/')
.then(data => generateInfo(data.results));

The error is clear, the object you are getting in data is not defined, that's why it does not have a result key.
Check that data is coming from the URL. When I fetch the URL there is JSON coming in.
Also note that in the second then you have for debugging is not returning the data variable, and that's why you get nothing afterwards.
Add a return statement like: return data;
Extra info related to the catch part from docs: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API if you want to check for errors look at the status code from response.
The Promise returned from fetch() won’t reject on HTTP error status even if the response is an HTTP 404 or 500. Instead, it will resolve normally (with ok status set to false), and it will only reject on network failure or if anything prevented the request from completing.

Change the fetchData function, remove .then block where you are getting final data, attach it when calling fetchData
function fetchData(url) {
return fetch(url)
.then(response => { return response.json()})
.catch(error => {console.log('Error with fetching API',
error)})}
fetchData('https://randomuser.me/api/')
.then(data =>generateInfo(data.results)); //success to the final promise
Now inside generate info use foreach() instead of map().Since for each user object you need to create card.
function generateInfo(results) {
results.forEach( userObj =>{
const card = document.createElement('div');
card.classList.add('card');
card.innerHTML = `
<div class="card-img-container">
<img class="card-img" src="${userObj.picture.thumbnail}" alt="profile picture">
</div>
<div class="card-info-container">
<h3 id="name" class="card-name cap">${userObj.name.first} ${name.last}</h3>
<p class="card-text">${userObj.email}</p>
<p class="card-text cap">${userObj.location.city}</p>
</div>
`;
gallery.appendChild(card);
})
}
Run the following snippet to check if it works.
const gallery = document.getElementById('gallery');
function fetchData(url) {
return fetch(url)
.then(response => { return response.json()})
.catch(error => {console.log('Error with fetching API', error)})}
function generateInfo(results) {
results.forEach( userObj =>{
const card = document.createElement('div');
card.classList.add('card');
card.innerHTML = `
<div class="card-img-container">
<img class="card-img" src="${userObj.picture.thumbnail}" alt="profile picture">
</div>
<div class="card-info-container">
<h3 id="name" class="card-name cap">${userObj.name.first} ${name.last}</h3>
<p class="card-text">${userObj.email}</p>
<p class="card-text cap">${userObj.location.city}</p>
</div>
`;
gallery.appendChild(card);
})
}
fetchData('https://randomuser.me/api/')
.then(data =>generateInfo(data.results));
<header>
<div class="header-inner-container">
<div class="header-text-container">
<h1>AWESOME STARTUP EMPLOYEE DIRECTORY</h1>
</div>
<div class="search-container">
</div>
</div>
</header>
<div id="gallery" class="gallery">
</div>

Related

Trouble rendering items from api feed

I am trying to display the latest and top stories on a single homepage using the hacker news API feed. I am using the .map so the code will loop over each story and display it all in a div with an id of output.
From what I am able to see I need to call the first API feed that will give me the day's top 500 results. The first API will only return story IDs as integers. I then need to make a 2nd API call using each story id from the original API call and map over it to get the corresponding data to each story to display on my site.
The code is working and the results are being displayed however when I switch between the latest stories and the top stories I keep getting different results at the top. Should I be using async and await somewhere In my code?
function getNewPosts() {
document.getElementById('output').innerHTML = ``;
fetch('https://hacker-news.firebaseio.com/v0/newstories.json?print=pretty')
.then(response => response.json())
.then(storyIds => {
storyIds.map(function (id) {
return (
fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`)
.then(response => response.json())
.then(story => {
// Display time human readable
let unixTimestamp = story.time;
let milliseconds = unixTimestamp * 1000;
let dateObject = new Date(milliseconds);
let humanDateFormat = dateObject.toLocaleString();
document.getElementById('output').innerHTML += `
<div class="card mb-3">
<h5 id="post-title" class="card-header data-title mb-1">${story.title}</h5>
<div class="card-body">
<p class="off-white-text mb-0">${story.type} by: ${story.by}</p>
<p class="off-white-text mb-0">posted: ${humanDateFormat}</p>
<p class="off-white-text mb-0">link to article:<a class="post-url" href="${story.url}" target="_blank"> Click here</a></p>
</div>
</div>
`
})
)
})
})
}
function getTopPosts() {
document.getElementById('output').innerHTML = ``;
fetch('https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty')
.then(response => response.json())
.then(storyIds => {
storyIds.map(function (id) {
return (
fetch(`https://hacker-news.firebaseio.com/v0/item/${id}.json?print=pretty`)
.then(response => response.json())
.then(story => {
// Display time human readable
let unixTimestamp = story.time;
let milliseconds = unixTimestamp * 1000;
let dateObject = new Date(milliseconds);
let humanDateFormat = dateObject.toLocaleString();
document.getElementById('output').innerHTML += `
<div class="card mb-3">
<h5 id="post-title" class="card-header data-title mb-1">${story.title}</h5>
<div class="card-body">
<p class="mb-0 off-white-text">${story.type} by: ${story.by}</p>
<p class="mb-0 off-white-text">Posted: ${humanDateFormat}</p>
<p class="mb-0 off-white-text">Link to article:<a class="post-url" href="${story.url}" target="_blank"> Click here</a></p>
</div>
</div>
`
})
)
})
})
}
The user is able to switch between the top and newest posts by clicking on a button for each on the homepage
<!-- Action buttons -->
<div class="row">
<div class="col-12 col-md-12 text-center">
<button id="getPosts" class="btn my-1" onclick="getNewPosts()">Read Latest News</button>
<button id="getPosts" class="btn my-1" onclick="getTopPosts()">Read Top News</button>
<button id="getPosts" class="btn my-1" onclick="clearNews()">Reset All News</button>
<hr class="text-white">
</div>
</div>
Thanks for any help in advance

I have a problem on The Movie DB API with VueJS

I work about a Movie App on The Movie DB API with VueJS but I have a problem; I'm trying to pull the poster_path data from The Movie App and print the picture on the page. The problem is; data is being get, the image is also visible, but when I refresh the page, the data cannot be retrieved. But when I remove or add ( / ) between w500 and ${movie.poster_path} in <img :src="`https://image.tmdb.org/t/p/w500/${movie.poster_path}`" > it's coming back. What should I do since we cannot do this all the time?
<script setup>
import axios from 'axios'
var movies = []
async function getMovies() {
const data = axios.get('https://api.themoviedb.org/3/movie/popular?api_key=**********&language=en-US&page=1')
const result = await data
result.data.results.forEach((movie) => {
movies.push(movie)
})
console.log(movies);
}
async function fetch() {
await this.getMovies()
}
getMovies()
</script>
<template>
<br><br><br><br>
<div class="">
<div class="">
<div class="" v-for="(movie, index) in movies" :key="index">
<div class="">
<img :src="`https://image.tmdb.org/t/p/w500/${movie.poster_path}`" >
</div>
</div>
</div>
</div>
</template>
<style scoped lang="scss">
#import '../public/Home.scss';
</style>

Alternative to then() function

I'm working on a project that requires a PayPal payment gateway. I found a simple tutorial online that works fine, with the exception that the PayPal Response is sent to the console log. Looking online for any instance were the then() function is used for other than logging to console came up empty. The present code:
return actions.order.capture().then(function (details) {
console.log(details);
needs to be changed, to a function other than then() in order to send the JSON object to the PHP processing page. Being a backend developer, I'm not sure what function that will be. Can anyone make a suggestion please? The entire code is as follows:
The HTML & JS Script
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Paypal Payment</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main id="cart-main">
<div class="site-title text-center">
<h3 class="font-title">Shopping Cart</h3>
</div>
<div class="container">
<div class="grid">
<div class="col-1">
<div class="flex item justify-content-between">
<div class="flex">
<div class="img text-center">
<img src="./assets/pro1.png" alt="">
</div>
<div class="title">
<h3>Canon EOS 1500D</h3>
<span>Electronics</span>
<div class="buttons">
<button type="submit"><i class="fas fa-chevron-up"></i> </button>
<input type="text" class="font-title" value="1">
<button type="submit"><i class="fas fa-chevron-down"></i> </button>
</div>
Save for later |
Delete From Cart
</div>
</div>
<div class="price">
<h4 class="text-red">$349</h4>
</div>
</div>
</div>
<div class="col-2">
<div class="subtotal text-center">
<h3>Price Details</h3>
<ul>
<li class="flex justify-content-between">
<label for="price">Products ( 1 item ) : </label>
<span>$399</span>
</li>
<li class="flex justify-content-between">
<label for="price">Delivery Charges : </label>
<span>Free</span>
</li>
<hr>
<li class="flex justify-content-between">
<label for="price">Amout Payble : </label>
<span class="text-red font-title">$399</span>
</li>
</ul>
<div id="paypal-payment-button">
</div>
</div>
</div>
</div>
</div>
</main>
<script src="https://www.paypal.com/sdk/js?client-id=ASbdZ8CH5kN5y98rzOuKMLPYsHl4QHLYcDGJ6lgaRjxiRp97t53sPWr1yG5vyd9mlHbyqw3vGUZaJsok&disable-funding=credit,card"></script>
<script>
// Create a Global var - the HTML charge is dummy stuff
window.charge = 0.27;
paypal.Buttons({
style : {
color: 'blue',
shape: 'pill'
},
createOrder: function (data, actions) {
return actions.order.create({
purchase_units : [{
amount: {
value: window.charge
}
}]
});
},
onApprove: function (data, actions) {
return actions.order.capture().then(function (details) {
console.log(details);
window.location.replace("https://localhost/PayPal_Simple/payPalResponse.php?q=good");
window.alert('This was successful.');
})
},
onCancel: function (data) {
window.location.replace("https://localhost/PayPal_Simple/payPalResponse.php?q=bad");
window.alert('Something went wrong!');
}
}).render('#paypal-payment-button');</script>
</body>
</html>
The PHP
<?php
// Get the Response from PayPal
$status = $_GET['q'];
// Once there is an object that can be tested, that will be used instead of ?q=
if($status = "good") {
echo "The payment was a success.<br />";
} elseif($status = "bad") {
echo "The charge was cancelled.";
} else {
echo "Something else went wrong.";
}
// Of course, this doesn't display anything
echo '<pre>';
print_r($_POST);
echo '<pre>';
// Insert data into the database
// Redirect the client to another page
?>
Thanks so much in advance for your help!
Cheers,
Rick
Do not capture on the client side and then send data to a backend. Instead, change to a proper server-side integration--the backend should be communicating with PayPal itself and sending data to the client on request.
Make two routes on your server, one for 'Create Order' and one for 'Capture Order', documented here. These routes should return only JSON data (no HTML or text). The latter one should (on success) store the payment details in your database before it does the return (particularly purchase_units[0].payments.captures[0].id, the PayPal transaction ID)
Pair those two routes with the following approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server
As This link reads , try using
onApprove
''''
const onApprove= new Promise((resolve, reject) => {
{resolve((data,actions) => {actions.order.capture(data,actions)}});
});
''''
buttonPushFunction
''''
async function doYourButtonPush() {
try {
await onApprove;
console.log("The Promise is resolved!", value);
} catch (e) {
console.error("The Promise is rejected!", error);
} finally {
function (details) {
console.log(details);
window.location.replace("https://localhost/PayPal_Simple/payPalResponse.php?q=good");
window.alert('This was successful.');
}
}
}
''''

how to view items from api and add item to cart

im fetching items image , name ,price ,about from API
i fetched each item and added it in html tag the problem when i press add to cart button nothing adding
i tried onclick function on the button and call item by id
html page
<div id="api-1" class="images full">
</div>
js file
window.onload = function(){
const name = document.getElementById('api-1');
const tableItems = document.getElementById('item');
const cartContent = document.getElementsByClassName('table-cart');
fetch('https://us-central1-guitar-chord-de94e.cloudfunctions.net/products')
.then(response => response.json())
.then(items => {
let html = '';
items.forEach(item =>{
// console.log(item.items.name)
html += `
<div class="container">
<img src=${item.items.image} class="item">
<div class="overlay">
<p style="color:white">${item.items.name}</p>
<p style="color: white;font-weight: bold;font-size: 17px">price: ${item.items.price}</p>
<div style="margin-top:60px;">
<button onclick="addToCart()" style="background-color: gold;margin:0%;">add <img width="16px" src="./image/icons/shopping-cart.png" alt=""></button>
</div>
</div>
</div>
`;
name.innerHTML= html;
})
});
}
function addToCart(){
fetch('https://us-central1-guitar-chord-de94e.cloudfunctions.net/products')
.then(response => response.json())
.then(sys => {
sys.forEach(item =>{ console.log(item.sys);
});
});
}
You have to pass the id, button click handler like in below code.
<button onclick="addToCart(${item.sys.id})" style="background-color: gold;margin:0%;"></button>
Here's a working pen. https://codepen.io/anon/pen/jjojVm
I am capturing id of the clicked item in addToCart function. Using that id, you can maintain a cart in the same page or you can goto to different page passing the same id in URL depending on your requirement.

How to iterate through an API response and insert proper data to identical divs?

I’m trying to create a „weather app” which is supposed to look like this: https://pictr.com/image/05IPpQ
I created an html markup, which looks like this:
<div class="card">
<div class="card__box card__box--blue" draggable="true" id="box1">
<div class="card__box--icon"></div>
<div class="card__box--city"></div>
<div class="card__box--country"></div>
<div class="card__box--weather"></div>
<div class="card__box--temperature"></div>
<div class="card__box--close">
<i class="fa fa-window-close" aria-hidden="true"></i>
</div>
</div>
<div class="card__box card__box--orange" draggable="true" id="box2">
<div class="card__box--icon"></div>
<div class="card__box--city"></div>
<div class="card__box--country"></div>
<div class="card__box--weather"></div>
<div class="card__box--temperature"></div>
<div class="card__box--close">
<i class="fa fa-window-close" aria-hidden="true"></i>
</div>
</div>
<div class="card__box card__box--grey" draggable="true" id="box3">
<div class="card__box--icon"></div>
<div class="card__box--city"></div>
<div class="card__box--country"></div>
<div class="card__box--weather"></div>
<div class="card__box--temperature"></div>
<div class="card__box--close">
<i class="fa fa-window-close" aria-hidden="true"></i>
</div>
</div>
<div class="card__box card__box--new" draggable="false" id="empty">
<div class="card__box--add">
<i class="fa fa-plus" aria-hidden="true"></i>
</div>
</div>
<p class="card__paragraph paragraph--smallest paragraph--grey text-center">Add more widgets</p>
</div>
I’m trying to make this actually work by the use of https://openweathermap.org.
This is an example of the APIs’ response which I’m getting:
https://samples.openweathermap.org/data/2.5/group?id=524901,703448,2643743&units=metric&appid=b6907d289e10d714a6e88b30761fae22
My problem is that I don’t know how to iterate through the response and fill all of my ‚boxes’ with proper data from the API. I want the first object from the list to fill the first box, etc. Here’s my code.
document.addEventListener('DOMContentLoaded', getWeather);
// These are hard coded ID's of the cities (only way to get data for multiple cities without a premium account)
const locations = ['524901', '703448', '2643743'];
const weather = new Weather();
function getWeather() {
const ui = new UI();
weather
.getWeather()
.then(response => ui.display(response.list))
.catch(err => console.log(err));
}
class Weather {
constructor(locations) {
this.apiKey = 'b5f8df2f8d10af0fda257b295738dcdd';
this.locations = locations;
}
// Fetch data from API
async getWeather() {
const response = await fetch(
`http://api.openweathermap.org/data/2.5/group?id=${locations}&units=metric&appid=${
this.apiKey
}`
);
const responseData = await response.json();
return responseData;
}
}
The display function is currently hardcoded to get the first object from the list, which is something i’m trying to avoid, and is currently left as is, just so that the app ‚works’.
class UI {
constructor() {
this.city = document.querySelector('.card__box--city');
this.country = document.querySelector('.card__box--country');
this.weather = document.querySelector('.card__box--weather');
this.temperature = document.querySelector('.card__box--temperature');
this.icon = document.querySelector('.card__box--icon');
}
display(response) {
this.city.textContent = response[0].name;
this.country.textContent = response[0].sys.country;
this.weather.textContent = response[0].weather[0].description;
this.temperature.textContent =
Math.ceil(response[0].main.temp) + String.fromCharCode(176);
const iconCode = response[0].weather[0].icon;
this.icon.style.backgroundImage = `url(http://openweathermap.org/img/w/${iconCode}.png)`;
}
}
I suspect there might be a problem with the UI constructor.

Categories