I am learning how to use fetch APIs and I can't seem to figure out why only 1 image is showing up when using the Unsplash API. I think it has something to do with map, but I'm not sure. Any help our guidance is appreciated.
document.getElementById("search").addEventListener("click", () => {
const searchTerm = document.getElementById("searchBox").value;
console.log(searchTerm);
fetch(
`https://api.unsplash.com/search/photos?client_id=e72d3972ba3ff93da57a4c0be4f0b7323346c136b73794e2a01226216076655b&query=${searchTerm}`
)
.then(response => response.json())
.then(data => {
console.log(data);
console.log(data.results);
let searchResults = data.results
.map(searchResults => {
return (document.getElementById("app").innerHTML = `<img src="${
searchResults.urls.small
}">`);
})
.join("");
});
});
Code Sandbox here: https://codesandbox.io/s/yq918mok29
The default 10 images should appear but only 1 shows up. How can I map through the images and show them on the page?
You're overwriting the element's content in each map iteration, so you only see the last one. Use map to build the markup, then drop it into the document.
Something like this:
.then(data => {
let imagesMarkup = '';
data.results
.map(searchResults => {
return (imagesMarkup += `<img src="${searchResults.urls.small}">`);
}); // note that the join was removed here
document.getElementById("app").innerHTML = imagesMarkup;
});
Demo
Related
I try to set data to my highchart with a fetch function but the dta is not displayed or even set to my chart element.
Here is my fetch function
fetch("data.csv")
.then(response => response.text())
.then((response) => {
//console.log("d"+response)
function csvToArray(str, delimiter = ",") {
let array = str.split("\n").map(function (line) {
return line.split(delimiter);
});
return array;
}
let array = csvToArray(response);
array.splice(0, 1);
array.splice((array.length-1),1)
let string =JSON.stringify(array);
let stringnew = string.replaceAll("\"","");
//console.log(csvToArray(response));
//console.log(csvToArray(response)[0]);
console.log(stringnew);
chart.series[0].setData(stringnew);
})
.catch(err => console.log(err))
as well as my data.csv file
time,data
1672683118394,12.00
1672683159084,10.00
1672683199305,9.00
I also see in the console the right output
[[1672683118394,12.00],[1672683159084,10.00],[1672683199305,9.00]]
its corrosponding to the Highcharts doku as I understood. But the data is not loaded.
Any help appreciated :)
stringnew is a string not a JSON object.
The issue is solved by using
JSON.parse(stringnew)
I am trying to fetch the weather forecast api json like I did with the current weather api, but it does not seem to work any way I try.
let inOneDay = {
fetchWeather: function(){
fetch("https://api.openweathermap.org/data/2.5/forecast?q=Dortmund&units=metric&cnt=1&appid=758fce6dd3722cf25cd213a13bbc5484"
).then(resp => resp.json())
.then(data => console.log(data));
}
};
I have no idea where I went wrong. I used the same logic to make the code below work:
let weather = {
fetchWeather: function(){
fetch("https://api.openweathermap.org/data/2.5/weather?q=Dortmund&units=metric&appid=758fce6dd3722cf25cd213a13bbc5484"
).then((response) => response.json())
.then((data) => this.displayWeather(data));
},
displayWeather: function(data){
const{icon,description} = data.weather[0];
const{temp} = data.main;
document.querySelector(".icon").src = "https://www.openweathermap.org/img/wn/" + icon + ".png";
document.querySelector(".celsius").innerText = Math.round(temp) + "°C";
document.querySelector(".desc").innerText = description;
}
}
Grateful for any ideas!
Examining the json reply from that API, it looks like the OP code expects different fields than the service provides.
const result =
{"cod":"200","message":0,"cnt":1,"list":[{"dt":1631577600,"main":{"temp":13.31,"feels_like":13.05,"temp_min":13.31,"temp_max":15.87,"pressure":1018,"sea_level":1018,"grnd_level":1007,"humidity":90,"temp_kf":-2.56},"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04n"}],"clouds":{"all":95},"wind":{"speed":1.42,"deg":94,"gust":2.29},"visibility":10000,"pop":0,"sys":{"pod":"n"},"dt_txt":"2021-09-14 00:00:00"}],"city":{"id":2935517,"name":"Dortmund","coord":{"lat":51.5167,"lon":7.45},"country":"DE","population":588462,"timezone":7200,"sunrise":1631595820,"sunset":1631641686}};
const result0 = result.list[0]; // notice .list[0]
const weather0 = result0.weather[0]; // notice weather[0]
const main = result0.main; // notice main is a sibling prop to weather
const temp = main.temp
console.log(`weather is ${JSON.stringify(weather0)}`);
console.log(`main is ${JSON.stringify(main)}`);
console.log(`temp is ${temp}`);
Be sure to check for errors before dereferencing the result. It also looks like the api provides a cnt prop which might indicate the number of elements in the list.
Working on modifying a project I'm learning from.
The initial project is to create a sort of infinitely scrolling Twitter Clone. Posts were grabbed from https://jsonplaceholder.typicode.com/ api, and I'm trying to add another level by bringing in images from another image placeholder API.
I'm a noob, so I was able to successfully grab data from both API's and populate the DOM. Trouble is, with my current structure, I'm repeating placeholder images as what I'm grabbing from the placeholder api is in 5 object blocks. Could use some help in making sure every post has a different photo. Thanks, total newb here. Wondering if I should just be populating an array of objects and working from there, but maybe there's a shortcut I'm missing?
const postsContainer = document.getElementById("posts-container");
const loading = document.querySelector(".loader");
const filter = document.getElementById("filter");
let limit = 5;
let page = 1;
//Fetch Posts from API
async function getPosts() {
const res = await fetch(
`https://jsonplaceholder.typicode.com/posts?_limit=${limit}&_page=${page}`
);
const data = await res.json();
return data;
}
//Fetch Photos from another API
async function getPhoto(photo) {
const res = await fetch(`https://randomuser.me/api`);
const data = await res.json();
photo = data.results[0].picture.thumbnail;
return photo;
}
//Show items in DOM
async function showPosts() {
const posts = await getPosts();
const pic = await getPhoto();
posts.forEach((post) => {
const postEl = document.createElement("div");
postEl.classList.add("post");
postEl.innerHTML = `
<div class="number">
<img class="profile-pic" src="${pic}" alt="user photo" />
</div>
<div class="post-info">
<h2 class="post-title">${post.title}</h2>
<p class="post-body">
${post.body}
</p>
</div>
</div>
`;
postsContainer.appendChild(postEl);
});
}
//Show loader and fetch more posts
function showLoading() {
loading.classList.add("show");
setTimeout(() => {
loading.classList.remove("show");
setTimeout(() => {
page++;
showPosts();
}, 1000);
}, 300);
}
//Show initial posts
showPosts();
window.addEventListener("scroll", () => {
const { scrollTop, scrollHeight, clientHeight } = document.documentElement;
if (scrollTop + clientHeight >= scrollHeight - 5) {
showLoading();
}
});
GitHub Repo: https://github.com/unsubstantiated-Script/infinite-scroller
TIA
Problem solved. Needed to move the pic variable inside my forEach loop. That and async the forEach loop.
I am making a web app that searches NASA's api and gets an image. That image is then painted to a canvas element and the user can make adjustments and edit the image. I am trying to take a snapshot of the final image and open it in another browser tab via canvas.toDataURL() but am getting a 'Tainted canvases may not be exported' error. I did not see anything about jsonp in the api docs. I am using the fetch api in react as seen below:
fetchPOD = (date) => {
let that = this;
fetch('https://api.nasa.gov/planetary/apod?&date=' + date + API_KEY)
.then(resp => resp.json())
.then(resp => {
let link = resp.url;
if(resp.media_type === 'image'){
let noImage = document.getElementsByClassName('no-image')[0];
noImage.style.display = 'none';
that.setState({
pod: resp.url,
podTitle: resp.title
})
} else {
that.setState({
pod: 'https://apod.nasa.gov/apod/image/1709/EclipseClimber_Struder_1080.jpg',
nonImageLink: link,
podTitle: 'A Hiker and the Eclipse'
})
let noImage = document.getElementsByClassName('no-image')[0];
noImage.style.display = 'block';
}
})
};
I am not running a server on this app. Any other way around this?
So I'm trying to use vanilla JavaScript and do a fetch from iTunes' API to create a page that allows a user to type in an artist name and then compile a page with like 15 top results. I'm using the following for my fetch:
function dataPull() {
fetch("https://itunes.apple.com/search?term=")
.then(function(response) {
if (response.status !== 200) {
console.log(response.status);
return;
}
response.json().then(function(data){
console.log(data);
let returnResponse = document.createElement("div");
let input2 = inputElement.value;
for (let i=0; i<data.length; i++){
if (inputElement===data[i].artistName){
console.log(data[i].artistName);
returnResponse.innerHTML = `
<div class="box">
<img src=${artWorkUrl30} alt="Album Image">
<p><span>Artist Name:</span>${data[i].artistName}</p>
<p><span>Track: </span>${data[i].trackName}</p>
<p><span>Album Name: </span>${data[i].collectionName}</p>
<p><span>Album Price: </span>${data[i].collectionPrice</p>
</div>
`;
results.appendChild(returnResponse);
}}
console.log(data);
});
}
)
The function is being called in a click event and I'm sure I can put everything from "let returnResponse" down to the append in another function. The issue I'm having is actually getting the API to show ANY results. At the moment if I type in Bruno Mars, Beethoven, or U2 it's not logging any data and it's giving me "Provisional Headers are Shown" when I check out the the Status Code.
Any thoughts on what I could do to make this better/work?
For full code:
jsfiddle
Typical fetch call will look like this.
fetch(`${url}`)
.then(response => response.json())
.then(json =>
// do something with the json
)
Modify your code and see if you can console.log() anything of note.
I would reccomend seperating your concerns. Making the dataPull function just get the results. That means you can use this code at other places without changing it.
Here the function returns the json object as a promise.
function dataPull(search) {
return fetch("https://itunes.apple.com/search?term="+search).then(res => res.json());
}
No you can call the dataPull function and resolve the promise. You'll have the result and can do what you want with it.
dataPull("test").then(res => {
console.log(res.results);
/*
res.results.forEach(item => {
div and span magic here
})
*/
})
Here's a link to a working JSFiddle.
https://jsfiddle.net/14w36u4n/