I am new to JavaScript and this is my first question here. I've been trying for week to render my RapidApi data on another HTML page. I made search form on my index page and then put its values as my api call parameters in order to influence my API response. I used fetch to do so. The issue is that my API data keeps rendering on the same index page which is understandable since I don't know how to render it on a separate page. This also means that my CSS styling options are limited since I cannot design API data as I want without messing up my index page. If you have any sort of solution that is not way too complicated I would really appreciate your help.
Here is part of my code:
const input = document.getElementById(`location`);
const guests = document.getElementById(`guests`);
const check = document.querySelectorAll(".date");
let id;
document.getElementById(`submit`).addEventListener(`click`, function (e) {
e.preventDefault();
locationId();
});
async function locationId () {
let hotelId = input.value;
const options = {
method: 'GET',
headers: {
'X-RapidAPI-Key': '//API key goes here',
'X-RapidAPI-Host': 'tripadvisor16.p.rapidapi.com'
}
};
let response = await fetch(`https://tripadvisor16.p.rapidapi.com/api/v1/hotels/searchLocation?query=${hotelId}`, options);
if (!response.ok) throw new Error(`Woops something went wrong`);
let data = await response.json();
let geoId = await (data.data[0].geoId);
id= parseInt(geoId);
return (fetch(`https://tripadvisor16.p.rapidapi.com/api/v1/hotels/searchHotels?geoId=${id}&checkIn=${check[0].value}&checkOut=${check[1].value}&pageNumber=1&adults=${guests.value}currencyCode=USD`, options))
.then(response => response.json())
.then(data => {
let list = data.data.data;
displayObjectElements(list)
function displayObjectElements (object) {
let display = ``;
let price = ``;
object.forEach(element => {
display+= `<div class = "objectResults">
<ul class="hotel__lists">
<li><h2 class = "title">${element.title}</h2></li>
<li><img class= "hotels--photo "src="${element.cardPhotos[0].sizes.urlTemplate.split("?")[0] + `?w=500&h=500`}" alt=image--photo/></li>
<li><p>Ranking:${element.bubbleRating.rating}☆ out of 5☆</p></li>`
if(!element.priceForDisplay) {
display+= `<li><p>There is no price to display</p></li>`
display+= `<li><button class="booking-btn">Click to book</button></li>`
} else {
price =element.priceForDisplay.substring(1);
price= parseInt(price);
// console.log(price);
display+= `<li><p>Price: $${price} in total</p></li>`
display+= `<li><button class = "booking-btn">Click to book</button></li>
</ul>
</div>`
// console.log(display);
}});
document.body.innerHTML = display;
}
})
.catch(err => console.error(err));
}
I already tried with localStorage and sessionStorage but as a newbie I am just now sure how to put the whole API data in storage. Also, I desperately tried with window.location object as well but as I assumed that did nothing but open a new tab. Again, thanks in advance for any help!
Related
i am currently stuck trying to code a search-bar for an JSON fil (linked via an API link and key). I am fairly new to coding and especially new to this field.
i currently cant get my function to work with onkeyup() maybe because its an async function? as i said im fairly new to this so idk, and I get an error for my "x.innerHTML = "" " saying "Cannot set properties of null", now i may look like an idiot here and missing something obvious but I would very much appreciate all answers:)
thanku for your time!
HTML:
<div id="søk"><input id="søkefelt" onkeyup="søk()" type="text" placeholder="Search..">
<ul id="listHolder"></ul>
</div>
javascript:
window.addEventListener("DOMContentLoaded", (Event) => {
async function søk() {
const apiKey = await fetch ("nyheter.json")
.then ((response) => response.json());
var data = await fetch ("https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=" + apiKey[0].apikey)
.then((response) => response.json());
let input = document.getElementById("søkefelt").value
input = input.toLowerCase();
let x = document.querySelector("listHolder");
x.innerHTML = ""
for (let i = 0; i < data.length; i++) {
const obj = data[i];
if (obj.title.toLowerCase().includes(input)) {
const elem = document.createElement("li")
elem.innerHTML = '${obj.title} - ${author}'
x.appendChild(elem)
}
};
}
søk();
});
querySelector requires # before ids
querySelector("#listHolder")
Im using an API and I fetch 9 pictures every time from said API. the API can display "pages", meaning if a "page=1" parameter is passed in the request I get the first 9 pictures from the database. "page=2" gives me the next 9 pictures and so on.
I want to have 2 buttons so on every click I get the next 9 pictures. I tried to do so using the API parameter change but haven't had much luck.
I ran across this thread:
Setting query string using Fetch GET request
but either it doesnt help me or I dont understand it enough.
Thanks!
my code is below:
const Home = ()=>{
let pageNumber = 1;
const [photosData, SetPhotosData] = useState([])
const url = `https://pixabay.com/api/?key=25540812-faf2b76d586c1787d2dd02736&per_page=9&page=`
const getImages = async()=>{
try {
const response = await fetch (url+pageNumber)
if (!response.ok) {
throw new Error();
}
const responseObj = await response.json();
const allPhotosData = responseObj.hits
SetPhotosData(allPhotosData)
}
catch (error) {
console.log(error);
}
}
useEffect(()=>{
getImages();
},[])
const getNextPage = ()=> {
pageNumber++;
console.log(pageNumber);
getImages();
}
const getPrevPage =()=>{
pageNumber--;
console.log(pageNumber);
getImages();
}
return(
<div>
<button onClick={getPrevPage}>prev</button>
<button onClick={getNextPage}>next</button>
<br/>
{photosData.map(singlePhotoData=>
<img
key={singlePhotoData.id}
src={singlePhotoData.largeImageURL}
/>)}
</div>
)
}
export default Home;
Your pageNumber will reset to 1 everytime you set a new state with SetPhotosData. You could fix this by using useRef.
const pageNumber = useRef(1);
...
const response = await fetch(url + pageNumber.current);
...
const getNextPage = () => {
pageNumber.current++;
console.log(pageNumber.current);
getImages();
};
const getPrevPage = () => {
if (pageNumber.current < 2) return;
pageNumber.current--;
console.log(pageNumber.current);
getImages();
};
Note that we also check if the pageNumber is not lower than 2 before decreasing it and calling the api to prevent the api from throwing a error, saying it has no page 0
my goal is to render some user data from API https://reqres.in/api/users?page=( this can be 1,2 or more if pages are available) and output it to a html table using JS / Promises. So initially I have managed to get the first page's data to the table and now I need it to be modified when I click "Load More" button it should delete the current data on the table and shows the page 2's data. This is my code so far
let userDataTable = document.getElementById("userData");
var tot_pages;
let pagesCount = 1;
console.log(tot_pages);
let getUSerInfo = function () {
fetch(`https://reqres.in/api/users?page=${pagesCount}`)
.then((response) => response.json())
.then((people) => {
let users = people.data;
tot_pages = people.total_pages;
console.log(users);
console.log(tot_pages);
for (let i = 0; i < users.length; i++) {
let htmlContent = `<tr><td>${users[i].id}</td><td><img src="${users[i].avatar}"/></td><td>${users[i].first_name}</td><td>${users[i].last_name}</td><td>${users[i].email}</td></tr>`;
userDataTable.insertAdjacentHTML("beforeend", htmlContent);
}
})
.catch(function (error) {
console.log(error);
});
};
getUSerInfo();
console.log(tot_pages);
document
.getElementById("load_btn")
.addEventListener("click", () => getUSerInfo());
also when there are no pages left to load (ex: when the last page's data is showing in the table then the "Load More" button should not be visible)
I'll explain what my idea was achieving this task : I was trying to create a global variable(tot_pages) initializing it to 1. Then inside the promise I was trying to assign the total pages from the object which I render via reqres.in and return it to the button as a counter or something. So as an ex : When I click the button the counter will increase(in this case the tot_pages variable will increase). Anyway after hours of trying on my own could not get this done yet. I do really appreciate if someone can help me out. Thank you for you time and consideration!
I think your code will work fine with you updating pagesCount variable on each successful API fetch, check this updated code. I've changed some variable names
let totalPages,
currentPage = 0,
loadMoreBtn = document.getElementById("load_btn");
// bind load more button
loadMoreBtn.addEventListener("click",getUSerInfo);
// fetch people
function getUSerInfo() {
// ignore if all data has been loaded
if(currentPage >= totalPages) return
const nextPage = currentPage + 1;
fetch(`https://reqres.in/api/users?page=${nextPage}`)
.then((response) => response.json())
.then((people) => {
const users = people.data,
userDataTable = document.getElementById("userData");
totalPages = people.total_pages;
// hide load more button
if(totalPages == nextPage) loadMoreBtn.style.visibility = 'hidden';
// udate table data
for (let i = 0; i < users.length; i++) {
let htmlContent = `<tr><td>${users[i].id}</td><td><img src="${users[i].avatar}"/></td><td>${users[i].first_name}</td><td>${users[i].last_name}< /td><td>${users[i].email}</td></tr>`;
userDataTable.insertAdjacentHTML("beforeend", htmlContent);
}
currentPage = nextPage;
})
.catch(function (error) {
console.log(error);
});
};
// fetch initial page
getUSerInfo();
I'm currently learning JavaScript, and has been playing around with API's (Yahoo Finance in this example).
The goal is to update a table of values with a specific stock's financial data - but I need to fetch the data, before it updates the data. Thought I could use await/async as shown, but it doesn't work.
Any pointers?
let stats;
let inputSymbol;
let stockName;
let stockSymbol;
let stockPrevClose;
let stockOpen;
let stockMarketCap;
let stockDayHigh;
function getStockStatistics(){
//Get symbol from input field
inputSymbol = document.getElementById("inputSymbol").value;
console.log(inputSymbol);
request();
updateStockTabel();
}
//Fetch data from Yahoo Finance API based on variables
const request = async () => {
const response = await fetch(`https://apidojo-yahoo-finance-v1.p.rapidapi.com/stock/v2/get-financials?symbol=${inputSymbol}®ion=US`, {
"method": "GET",
"headers": {
"x-rapidapi-key": "---",
"x-rapidapi-host": "---"
}
});
const data = await response.json();
stats = data;
console.log(data);
}
//Update statistics in table based on values from Yahoo Finance JSON object
function updateStockTabel() {
//Change properties
stockPrevClose = stats.summaryDetail.previousClose.raw;
stockOpen = stats.summaryDetail.open.raw;
stockMarketCap = stats.summaryDetail.marketCap.fmt;
stockDayHigh = stats.price.regularMarketDayHigh.fmt;
stockName = stats.price.longName;
stockSymbol = stats.meta.symbol;
//Connect document properties with variables
document.getElementById("stocPrevClose").innerText = stockPrevClose;
document.getElementById("stockOpen").innerText = stockOpen
document.getElementById("stockMarketCap").innerText = stockMarketCap;
document.getElementById("dayHigh").innerText = stockDayHigh;
document.getElementById("stockName").innerText = stockName;
document.getElementById("stockSymbolOutput").innerText = stockSymbol;
}
You have 2 options mainly: leave your code exactly as it is now, but use this to wait to run updateStockTabel :
request().then(() => updateStockTabel());
OR change your getStockStatistics to an async function to do something pretty similar, but with async/await syntax:
async function getStockStatistics(){
//Get symbol from input field
inputSymbol = document.getElementById("inputSymbol").value;
console.log(inputSymbol);
await request();
updateStockTabel();
}
I want to rerun the search or populate the results as if the user never left.
So I visit the page, search for cats and get some results based on cats. I close the tab, come back later, and rather than find myself on a fresh page that has no results, I’m provided with the results from my last search. I am only allowed to use Javascript and local storage to achieve this. Here is my JS file:
var search = document.getElementById('searchTerm');
if(!localStorage.getItem('input')) {
populateStorage();
}
// To set the event to listen to
const form = document.querySelector('.js-search-form');
// To listen when user hits submit or press enter
form.addEventListener('submit', (e) => {
// Start of the query string
const base = `https://api.themoviedb.org/3/search/movie?include_adult=false&page=1&`;
// Extension of the query string
const searchTerm = document.querySelector('#searchTerm').value;
const language = `en-US&`;
const api_key = `7ab3cb18b4ad4a07bbd8bb01acfa7091`;
// The complete build of the url
const url = `${base}query=${searchTerm}&language=${language}api_key=${api_key}`;
// The get method
const option = {
method: 'GET'
}
// Stops the default action
e.preventDefault()
fetch(url)
//Parse data
.then( response => {
if (response.ok) {
return response.json()
} else {
throw response
}
})
// Do something with data
.then( data => {
console.log(data)
// Output results
let resultElement = '';
if(data.results.length > 1) {
resultElement += `
<h2><span>Results for ${searchTerm}</span></h2>
<section class="js-search-results clearfix">
`;
if(data.results) {
data.results.forEach(function(results){
resultElement += `<article class="item">
<div class="container">
<img src="https://image.tmdb.org/t/p/w500${results.poster_path}"/>
<div class="content">`;
if(results.title.length > 17) {
resultElement += `<h3>${results.title.substr(0,17)}...</h3>`;
} else {
resultElement += `<h3>${results.title}</h3>`;
}
resultElement += `<p>Released: ${results.release_date}</p>`;
resultElement += `</div>
</div>
</article>`;
});
resultElement += `</section>`;
populateStorage()
} else {
resultElement += '<p class="no-results">No results</p>';
}
document.querySelector('.js-search-results').innerHTML = resultElement;
}
})
.catch(err => {
console.log(err)
})
})
function populateStorage() {
localStorage.setItem('searchTerm', document.getElementById('searchTerm').value);
}
EDIT -
You are calling localStorage.getItem('input'); but you are saving the local storage item as searchTerm please make these names consistent with one another
you either need to change localStorage.getItem('input')
TO
localStorage.getItem('searchTerm');
OR
change localStorage.setItem('searchTerm', document.getElementById('searchTerm').value)
TO
localStorage.setItem('input', document.getElementById('searchTerm').value)
-Edit-
Assuming that this is wrapped in a document ready function, update your initial check of storage to look like this...
var search = document.getElementById('searchTerm');
//This assumes that you corrected your getItem to reference 'searchTerm'
if(!localStorage.getItem('searchTerm')) {
populateStorage();
}
else {
search.value = localStorage.getItem('searchTerm');
}
Your code never makes a call to actually populate that field so this should fix that.