How to fetch data from API on button click - Javascript? - javascript

I've got this part of code:
fetch(`https/someapi.com/data`)
.then(response => {
return response.json()
}).then(randomProduct => {
document.querySelector('#list').innerHTML = `
<span>${randomProduct.value}</span>
<button id="refresh-button" type="button">Refresh</button>
`;
var clickOnButton = document.querySelector("#refresh-button");
clickOnButton.addEventListener("click", () => {
})
})
How to I make this onClick event refresh the data the I read from API and display a new one?

first you need a button to make the fetch request
const fetchDataBtn = document.querySelector('#fetchdata')
const result = document.querySelector('#result')
// gets data from API and sets the content of #result div
const getData = function() {
result.innerText = 'Loading....'
fetch('https://dummyjson.com/products')
.then(res => res.json())
.then(data => {
result.innerText = JSON.stringify(data, null, 2)
})
.catch(error => console.log(error))
}
// add event listener for #fetchdata button
fetchDataBtn.addEventListener('click', getData)
const fetchDataBtn = document.querySelector('#fetchdata')
const result = document.querySelector('#result')
// gets data from API and sets the content of #result div
const getData = function() {
result.innerText = 'Loading....'
fetch('https://dummyjson.com/products')
.then(res => res.json())
.then(data => {
result.innerText = JSON.stringify(data, null, 2)
})
.catch(error => console.log(error))
}
// add event listener for #fetchdata button
fetchDataBtn.addEventListener('click', getData)
<button id="fetchdata">FETCH</button>
<div id="result"></div>

you can wrap it all in a function and call it like this
const fakeApi = () => new Promise(resolve => setTimeout(() => resolve({
value: Math.floor(Math.random() * 100)
}), 500))
const getData = () => fakeApi().then(randomProduct => {
document.querySelector('#main').innerHTML = `
<span>${randomProduct.value}</span>
<button id="refresh-button" type="button" onclick="getData()">Refresh</button>`
})
getData()
<div id="main"></div>

I'm not sure if I understood your question correctly, but from what I'be got you want to edit only the data on fetch no need to create a button and a listener every time. Place the fetch inside a dedicated function which is called onClick of the button in the fetch just edit the value.

Related

Using fetch and randomuser.me, how do I return multiple results?

I'm trying to use randomuser.me and I have the fetch request set up properly. I'm returning a single user. However, I want to return 5 comma separated users.
According to randomuser.me's documentation, I only need to append the fetch URI with ?results=5 (or any number I choose) and the multiple users are returned.
I've done this in the snippet below, but I'm still only returning a single user.
How do I return a comma separated result of 5 users?
window.onload = () => {
randomUserGenerator();
};
const randomUserGenerator = () => {
fetch("https://randomuser.me/api/?results=5")
.then((res) => {
return res.json();
})
.then((data) => {
showRandomUserData(data);
});
};
showRandomUserData = (randomUser) => {
document.getElementById("name").innerText =
`${randomUser.results[0].name.first} ${randomUser.results[0].name.last}`;
};
<h3><u>Users:</u> <span id="name"></span></h3>
using results[0] ... you're only USING the first user
Something like this may help you along
window.onload = () => {
randomUserGenerator();
};
const randomUserGenerator = () => {
fetch("https://randomuser.me/api/?results=5")
.then((res) => {
return res.json();
})
.then((data) => {
showRandomUserData(data);
});
};
showRandomUserData = (randomUser) => {
// combine all users
const users = randomUser.results.map(({name: { first, last}}) => `${first} ${last}`).join(', ');
// show them
document.getElementById("name").innerText = users;
};
<h3><u>Users:</u> <span id="name"></span></h3>

How to wait for async emits in Vue 3?

I'm triggering a submit event from a parent component, which emits an image data-url and a body text from two child components to the parent:
<ImgUploadComponent :triggerEmit="state.submit" #emitImage="getImage"/>
<EditorComponent :triggerEmit="state.submit" #emitBody="getBody"/>
The image and body are fetched with these functions:
const getImage = async (image) => {
form.image = await image
// arrives after storeRecord
}
const getBody = async (body) => {
form.body = await body
// arrives before storeRecord
}
and sent to the database in this function:
const storeRecord = async () => {
state.submit = true
await getImage
await getBody
console.log(form.image) // returns undefined
form.post('/admin/posts')
}
Problem is that the body arrives before form.post is sent but the image arrives after. When I wrote this function, it used to work but now it doesn't and I can't figure out why. How do you do it right?
Thanks to #Estus' suggestion, I was able to use a watcher to solve my problem:
const storeRecord = () => {
state.submit = true
watch(() => form.image, () => {
form.post('/admin/kreationen')
})
}
const getImage = (image) => {
form.image = image
}
const getBody = (body) => {
form.body = body
}

Fix Fetch data form API and print it on HTML with JavaScript

I want to fetch data from API and show it on HTML by elementID with JavaScript, Please help what I wrong in this code below.
<div id="priceChange"></div>
<script>
setInterval(tradestime, 5000);
function tradestime(){
fetch("https://api.binance.com/api/v1/ticker/24hr?symbol=LTCUSDT")
.then(
(res) => {
const data = res.json();
}
)
document.getElementById("priceChange").innerHTML = data.PriceChange;
}
</script>
Please fix this code.
You should use res.json() because you want data in JSON format. which will return promise and then you can get data. You should read fetch docs
fetch("https://api.binance.com/api/v1/ticker/24hr?symbol=LTCUSDT")
.then(res => res.json())
.then(data => el.innerHTML = data.priceChange)
key should be priceChange not PriceChange.
You can use parseFloat + toFixed as:
el.innerHTML = Number.parseFloat(data.priceChange).toFixed(2);
setInterval(tradestime, 5000);
const el = document.getElementById("priceChange");
function tradestime() {
fetch("https://api.binance.com/api/v1/ticker/24hr?symbol=LTCUSDT")
.then(res => res.json())
.then(data => el.innerHTML = data.priceChange)
}
<div id="priceChange"></div>
You can also use async-await here
setInterval( tradestime, 5000 );
const el = document.getElementById( "priceChange" );
async function tradestime() {
const res = await fetch( "https://api.binance.com/api/v1/ticker/24hr?symbol=LTCUSDT" )
const data = await res.json();
el.innerHTML = data.priceChange;
}
<div id="priceChange"></div>

Can't make a search based on input value using fetched data . Getting a filter error

Attempting to make an inquiry which depends on input esteem. I am utilizing countries rest programming interface. The wished yield is the parsed information from API which is templated by handlebars markup. It would be ideal if you clarify in what capacity can fix my code. Much obliged to you.
import markupAdd from "../templates/markup.hbs";
const divInfo = document.querySelector("#main-container");
const search_input = document.querySelector(".input-field");
let search_term = "";
let countries;
const fetchCountries = () => {
countries = fetch(
"https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
).then((res) => res.json());
};
const showCountries = () => {
divInfo.innerHTML = "";
fetchCountries();
countries
.filter((country) =>
country.name.toLowerCase().includes(search_term.toLowerCase())
)
.map((item) => markupAdd(item))
.join("");
divInfo.insertAdjacentHTML("beforeend", infoBlock);
};
search_input.addEventListener("input", (e) => {
search_term = e.target.value;
showCountries();
});
handlebars
<div id="country-container">
<p class="country">{{name}}</p>
<img src="{{flag}}" alt="{{name}}" width="600" height="400">
<div id="info-container">
<p class="capital">Capital: {{capital}}</p>
<p class="population">Population: {{population}} </p>
<ul class="langs">
{{#each languages}}
<li class="language">Languages: {{name}}</li>
{{/each}}
</ul>
</div>
</div>
At the present time, after inputed any letter I am getting this kind of error
apiInfo.js?b765:22 Uncaught TypeError: countries.filter is not a function
at showCountries (apiInfo.js?b765:22)
at HTMLInputElement.eval (apiInfo.js?b765:28)
The fetchCounries function is not returning anything, one approch to solve the issue will be following.
Convert the Function to the async function
and then return the data your will get.
const fetchCountries = async () => {
let countries = await fetch(
"https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
);
let country = await countries.json();
return country;
};
const showCountries = () => {
divInfo.innerHTML = "";
fetchCountries().then(countries =>{
countries
.filter((country) =>
country.name.toLowerCase().includes(search_term.toLowerCase())
)
.map((item) => markupAdd(item))
.join("");
divInfo.insertAdjacentHTML("beforeend", infoBlock);
}).catch(err => {
console.log(err)
})
};
Async Function also returns a promise so later you can handle this using then catch block
to do it without the async await and do it more clear, you can do something like this
const fetchCountries = () => {
fetch(
"https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages"
)
.then((res) => res.json())
.then((data) => {
showCountries(data);
})
.catch((err) => {
console.log(err);
});
};
const showCountries = (countries) => {
divInfo.innerHTML = "";
countries
.filter((country) =>
country.name.toLowerCase().includes(search_term.toLowerCase())
)
.map((item) => markupAdd(item))
.join("");
divInfo.insertAdjacentHTML("beforeend", infoBlock);
};
Change your function like this :
async function fetchCountries() {
response = await fetch ("https://restcountries.eu/rest/v2/all?fields=name;flag;capital;population;languages");
return await response.json();
};
And where you are calling the function , just use .then to get the data.
fetchCountries().then().catch();

Using RxJS and axios, how do you fetch data onClick in React component?

I'm struggling with how to fetch data using RxJS and axios onClick in a React component. But getting closer, I think. Any attempts I've tried either run when component mounts, not onClick, or don't run at all even onClick.
Basically, how to call onClick and how to pass a payload. There just seems to be nothing online to explain this which i would expect to be a common situation.
const MyComponent = () => {
const [data, setData] = useState(null);
const getData$ = new Subject(observer => {
axios
.post(`/my-url/`, **how to get payload to here**)
.then(response => {
observer.next(response.data);
observer.complete();
})
.catch(error => {
observer.error(error);
});
});
useEffect(() => {
const subs = getData$.subscribe({
next: res => setData(res),
});
return () => subs.unsubscribe();
}, []);
return (
<Button onClick={() => getData$.next(payload)} />
);
};
Any help appreciated.
you can pass in the payload in getData like this
const getData$ = (payload) => new Subject(observer => {
axios.post(`/my-url/`, payload)
.then(response => {
observer.next(response.data);
observer.complete();
})
.catch(error => {
observer.error(error);
});
});
This basically just creates an anonymous function called getData that returns your Subject. It's equivalent to this:
const getData$ = function (payload) {
return new Subject(observer => {
axios.post(`/my-url/`, payload)
.then(response => {
observer.next(response.data);
observer.complete();
})
.catch(error => {
observer.error(error);
});
});
};

Categories