JS: problem with for loop (only one image is shown) - javascript

I am completely new to javascript and web development.
I'm having a problem with the for loop; what happens to me is that the ids come back to me all together and not individually in order to retrieve the relative image and title through the id, so I can't recover images and title from the json array.
Specifically I get the error:
Uncaught TypeError: Cannot read properties of undefined (reading 'immagine') at XMLHttpRequest.xmlhttp.onreadystatechange
Warning: I have no problems in how to retrieve items in a json array because I know how to do it very well
This is my code:
//here I get all the articles, so my json array
var xmlhttp = new XMLHttpRequest();
var url = "https://wjko5u1234.execute-api.us-east-2.amazonaws.com/articles";
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var allart = JSON.parse(this.responseText);
var container=document.getElementById("slideshow")
for(var i = 0; i < allart.Items.length; i++)
{
container.innerHTML += '<div class="slideshow-container"></div>';
document.getElementById("id").innerHTML += "<br/>" + allart.Items[i].id;
myFunction1(allart.Items[i].id);
}
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
//here I pass the id via function call, and for each id I want to retrieve image and title which has that specific id only i get the set of ids without having one at a time to retrieve what i need
function myFunction1(id) {
var xmlhttp = new XMLHttpRequest();
var url = "https://wjko5u1234.execute-api.us-east-2.amazonaws.com/articles/"+id;
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myArr = JSON.parse(this.responseText);
console.log(myArr);
document.getElementById("img1").src="articoli_img/"+myArr.Item.immagine;
document.getElementById("title1").innerHTML = myArr.Item.titolo;
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
I would be very thankful for any help.

It seems that "Item" prop doesn't exist in returned object (located in myFunction1()) (did you mean to write myArr.immagine?)
Since you are new: I recommend to use for-each loops in collections, by using:
for(let item of allart.Items) {
.....
}

Related

How to subset specific object properly in JS

I'm currently doing some practice and i want to print the titles of each movie on this api:
https://jsonmock.hackerrank.com/api/movies?Year=1998
Basically, I want each title to be printed for the first page (or preferably a specific page).
This is the code I have:
<script>
function printTItles(year) {
var res;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(this.responseText);
for(var i=0;i<res.per_page;i++){
document.getElementById("demo").innerHTML = res.data.i.Title;
}
};
}
xmlhttp.open("GET", "https://jsonmock.hackerrank.com/api/movies?Year=<year>", true);
xmlhttp.send();
}
</script>
I know the problem is in res.data.i.title but I'm not sure how to fix it.
You are trying to access the element at the index i in your loop, like you would access a property of an object. To get the element at position i in your res.data array, you need the square bracket access [ ]
Also, you are not replacing the year parameters in your request for the year parameters passed to your function. You might want to check that out.
Here I have use the year 2018 as an example.
function printTItles(year) {
var res;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(this.responseText);
for(var i=0;i<res.per_page;i++){
document.getElementById("demo").innerHTML = res.data[i].Title;
}
};
}
xmlhttp.open("GET", "https://jsonmock.hackerrank.com/api/movies?Year=2018", true);
xmlhttp.send();
}
printTItles();
<div id="demo"></div>
You could add some more improvement. For example, at each iteration, you are replacing the content of your #demo element. This cause only the last title to be shown. You could, instead, append the data to the already existing html of the div. Or, like I did in this case, build your string before setting it as the new innerHTML value.
function printTItles(year) {
var res;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
res = JSON.parse(this.responseText);
var output = "";
for(var i=0;i<res.per_page;i++){
if(res.data[i]) {
output += res.data[i].Title + '<br />';
}
}
document.getElementById("demo").innerHTML = output;
};
}
xmlhttp.open("GET", "https://jsonmock.hackerrank.com/api/movies?Year=2018", true);
xmlhttp.send();
}
printTItles();
<div id="demo"></div>
I've also added a condition to check if there is an element at res.data[i].

How to assign data to a variable from a GET request

I am trying to pass an ID to the API and have the server return the object and then assign that object to a variable but I cant quite figure out where I am going wrong
function createList() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200 ){
var theList = JSON.parse(this.responseText);
console.log("the name of the current list given the ID is: " + theList.name);
}
};
xhttp.open('GET', 'todoapi/lists/' + editID , true);
xhttp.send();
}
I want the end result to be a variable that is storing an object, obtained by passing the API the object's id

JavaScript - Push objects within object to global array

ORIGINAL QUESTION
I'm trying to write a function in JavaScript that allows for articles from another source to be loaded on another page using an XMLHTTPRequest.
Each article is a JavaScript object containing the link, image, summary etc.
Each request will retrieve 5 articles, but I only want to show 4 articles on each button click. Because of this, I want to push the articles (objects) to a global array.
Since I'm fairly new at using XMLHTTPRequests, I can't find how to do this.
Everything works except for:
var i;
for (i = 0; i < newArticles.length; i++) {
articles.push(newArticles[i]);
}
newArticles is an object containing the 5 articles (objects) which I'm trying to push to the global array titled articles.
My code:
var articles = [];
document.getElementById("fc-blog-button-loadmore").addEventListener("click", receiveNewArticles);
function receiveNewArticles() {
var http = new XMLHttpRequest();
var url = "thelinktothepagewith5newarticles.json";
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
var newObj = JSON.parse(http.responseText);
var newArticles = (newObj.blog.articles);
console.log(newObj);
console.log(newArticles);
var i;
for (i = 0; i < newArticles.length; i++) {
articles.push(newArticles[i]);
}
console.log(articles);
}
}
http.open("GET", url, true);
http.send();
}
SOLVED
After the helpful comments my code currently looks like this:
var articles = [];
document.getElementById("fc-blog-button-loadmore").addEventListener("click", receiveNewArticles);
function receiveNewArticles() {
var http = new XMLHttpRequest();
var url = "http://freshcotton-dev.webshopapp.com/nl/blogs/blog/page2.html?format=json";
http.onreadystatechange = function() {
if(http.readyState == 4 && http.status == 200) {
var newObj = JSON.parse(http.responseText);
var newArticles = (newObj.blog.articles);
console.log(newObj);
console.log(newArticles);
articles.push(...Object.values(newArticles))
console.log(articles);
}
}
http.open("GET", url, true);
http.send();
}
Problem has been solved!
You can solve the issue simply by using [spread operator][1] ...
articles.push(...Object.values(newArticles));
[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

Remove a line from JSON parse

I am working with JIVE JSON RESTFul API and on their API they have a security
(I am referring to the throw 'allowIllegalResourceCall is false.'; )
throw 'allowIllegalResourceCall is false.';
{
"id" : "52104",
}
I am using this code to try to PARSE IT:
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var myObj = JSON.parse(this.responseText);
document.getElementById("topdisplay").innerHTML = myObj.id;
}
};
xmlhttp.open("GET", "http://mysite/API/",true);
xmlhttp.send();
And I am getting an error because of that starting line.
I looked everywhere to try finding a solution to skip that to the JSON PARSE would work but I can't seem to find a way that works to do it.
Also I know that the parsing code works because when I remove the first line it works perfectly.
Any help?
JIVE REST API introduced this to help prevent against JSON Hijacking back when web browsers were susceptible.
You'll need to first find {, and do a substring from that position to the end of the string.
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = this.responseText
var myObj = JSON.parse(this.responseText.substring(this.response.indexOf('{')));
document.getElementById("topdisplay").innerHTML = myObj.id;
}
};
xmlhttp.open("GET", "http://mysite/API/",true);
xmlhttp.send();
NOTE:
using RegEx, you'll need to find the first line with throw and ending in a semi-colon, if found replace with an empty string.
JSON.parse(response.replace(/throw.*;/, "").trim());

How to use Get to parse multiple JSON files?

I'm having some trouble parsing more than one JSON file at a time.
Basically, I have a web form with checkboxes that control which polygons to draw on a Google Map.
Depending what the user selects, that determines which JSON files (and geo coordinates) to get and parse. The script below works except for the last step - it always only returns the very last JSON file regardless how many are selected.
This is my first post to Stackoverflow and I'm new to JS, so any suggestions or different ways to approach this problem would be appreciated!
var xmlhttp = new XMLHttpRequest(); //
xmlhttp.onreadystatechange = function() { //parse json file
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var myArr = JSON.parse(xmlhttp.responseText);
console.log(myArr);
}
}
function goCheck() {
var input = document.getElementsByTagName('input');
var checkboxCount = 0;
var selections = [];
var urlArray = [];
for (var i=0, length = input.length; i<length; i++) {
if (input[i].checked === true) {
j = input[i].value;
selections.push(j); // store values for checkbox selections in array
checkboxCount++; // keep track how many were checked
var url = "https://mywebsite.ca/" + j + ".txt";
urlArray.push(url); // store urls in array
}
}
console.log(checkboxCount); // number of boxes checked
console.log(selections); // array with the selection values
console.log(urlArray); // an array with the json urls
// 2nd Loop - iterate over URL array and call function to get json object
for (var i=0, length = urlArray.length; i<length; i++) {
console.log(urlArray[i]);// check that loop is working
xmlhttp.open("GET", urlArray[i], true);
xmlhttp.send();
}}
You are reassigning what xmlhttp is doing each time. Create a new var each time and assign the state change handler to it and it should work. E.g.
for (var i=0, length = urlArray.length; i<length; i++) {
console.log(urlArray[i]);// check that loop is working
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() { //parse json file
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var myArr = JSON.parse(xmlhttp.responseText);
console.log(myArr);
}
};
xmlhttp.open("GET", urlArray[i], true);
xmlhttp.send();
}}
When you recall open on the same XMLHttpRequest you are abandoning the last request, but if you create a new one each time, they will each handle their own requests.
Aside, if you have control over the server side, a server method that takes in an array of files to get and returns a json array in a single AJAX call seems like the way to go long term.
You need to have a new XMLHttpRequest for each file. Replace your last loop with:
var xmlhttp;
for (var i=0, length = urlArray.length; i<length; i++) {
xmlhttp = new XMLHttpRequest(); //
xmlhttp.onreadystatechange = function() { //parse json file
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var myArr = JSON.parse(xmlhttp.responseText);
console.log(myArr);
}
}
console.log(urlArray[i]);// check that loop is working
xmlhttp.open("GET", urlArray[i], true);
xmlhttp.send();
}}

Categories

Resources