Hello I am trying to populate a select list using JSON and I am not getting any console errors however the list is not getting populated at all.
This is my html code
<select id="player_dropdown1">
</select>
This is my javascript code
var request = new XMLHttpRequest()
request.open('GET','https://cors-
anywhere.herokuapp.com/https://fantasy.premierleague.com/api/bootstrap-static/' , true)
request.onload = function() {
let dropdown = document.getElementById('player_dropdown1');
dropdown.length = 0;
let defaultOption = document.createElement('option');
defaultOption.text = 'Select a player';
dropdown.add(defaultOption);
dropdown.selectedIndex = 0;
var data = JSON.parse(this.response);
if (request.status >= 200 && request.status < 400) {
let option;
for (let i = 0; i < data.length; i++) {
option = document.createElement('option');
option.text = data.elements[i].firstname + data.elements[i].secondname;
option.value = data.elements[i].secondname;
dropdown.add(option);
}
} else {
}
console.log(data);
}
request.onerror = function() {
console.error('An error occurred fetching the JSON');
};
request.send();
I am not sure why the dropdown list is not getting populated. The json is getting parsed successfully to the console.
If you have a document.getElementById(ID) returning null or undefined on a very obviously defined ID, it is because your DOM element having the ID in question does not exist when the javascript is loaded.
You have two solutions:
- Include the script after the DOM element having the ID is declared
- Delay the execution of your code until the document is loaded, see this question for plain javascript.
I would personally choose the first solution if there are no "obligations" (such as code pattern) to include the javascript before the end of the document. This is going to save you the lines of codes of the event handlers and performance-side it does not add any more operations during the loading of the webpage.
Related
I am building a simple open source Chromium extension that retrieve some data from several urls and then update the DOM. I could find another way to do this than by adding the line to update the DOM inside the callback http1.onreadystatechange
My XMLHttpRequest requests were often stuck on http1.readyState = 3 so I have added a 3rd parameter to http1.open("GET"); to make the request synchronous like this:
http1.open("GET", url, false);
But I am still getting these errors:
results[1].join is not a function at XMLHttpRequest.http.onreadystatechange
annot read property 'join' of undefined at XMLHttpRequest.http.onreadystatechange
Even thought they don't prevent the script from running, I think this isn't the right way to do what I want. So here is my question: how to update the DOM with the responses from several XMLHttpRequest request? Let's say I need to retrieve and compare all the data before updating the DOM. Then is there a way to process all the data at once after we have retrieve all of them (cf my comment on the last line)?
Here is the relevant part of my script, the full script is available here:
var urls = [
["https://www.cnrtl.fr/morphologie/" + keyword, "vtoolbar", "morf_sound"], //best for plural
["https://www.cnrtl.fr/synonymie/" + keyword, "syno_format"],
]
// for test set keyword to any of this word : hibou, tribal, aller, lancer
var resultdiv = document.getElementById("result")
resultdiv.innerText = "requete en cours";
var results = [];
var errors = [];
urls.forEach((item, index) => {
var http = new XMLHttpRequest();
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
parser = new DOMParser();
var ulr1response = parser.parseFromString(http.responseText, "text/html");
if (index == 0) {
//retrieve the data needed, save then in a list and push this list to the main list result
} else if (index == 1) {
//retrieve the data needed, save then in a list and push this list to the main list result
}
// update the DOM
if (results[1] == "") {
resultdiv.innerHTML = results[0].join(", ") + "</br></br>Pas de synonymes trouvés"
} else {
resultdiv.innerHTML = "<b>" + results[0].join(", ") + "</br></br>Synonymes:</b></br>● " + results[1].join('</br>● ')
}
} else {
errors.push(index);
resultdiv.innerText = "Erreur: " + index + " " + http.readyState + " " + http.status;
}
}
http.open("GET", item[0], false);
http.send(null); // null = no parameters
});
// it would be simplier if I could update the DOM here and not in http.onreadystatechange
If you want to execute some code once all requests have succeeded, you can try using Promise.all together with Fetch.
let keyword = "beaucoup";
let parser = new DOMParser();
let urls = [
["https://www.cnrtl.fr/morphologie/" + keyword, "vtoolbar", "morf_sound"], //best for plural
["https://www.cnrtl.fr/synonymie/" + keyword, "syno_format"]
];
let fetchPromises = urls.map(
item => fetch(item[0]).then(
response => parser.parseFromString(response.text(), "text/html")
)
);
Promise.all(fetchPromises).then(
results => {
// code in here executes once all fetchPromises have succeeded
// "results" will be an array of parsed response data
console.log(results);
}
).catch(console.error);
I have some JavaScript code that I use to retrieve data from a json file and populate a dropdown list.
Everything was working fine.
I added some code and it went into an infinite loop.
I deleted this code but since then it no longer works on the HTTP server I setup using Python.
HOWEVER it works perfectly fine when I load it on a network server.
I deleted Python, reinstalled and still not working.
Logically it can't be the code because it works on the network server... I am totally lost. Any and all help much appreciated. I am getting now where fast. (I can't work from the network server so need this working locally.)
Below is the javascript
//this will hold the data from JSON
var teamSkillsData
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
//retrieve data from the external json file
var response = JSON.parse(xhttp.responseText);
teamSkillsData = response.teamSkills;
var select = document.getElementById("teamList");
alert("nn");
//populate the teamList drop down menu
for(var i = 0; i < teamSkillsData.length; i++) {
//assign the team names
var opt = teamSkillsData[i].team;
var el = document.createElement("option");
el.textContent = opt;
el.value = i;
select.appendChild(el);
}
// Typical action to be performed when the document is ready:
document.getElementById("demo").innerHTML = xhttp.responseText;
}
};
xhttp.open("GET", 'Data.json', true);
xhttp.send();
function teamChanged(teamSelected)
{
var skills = teamSkillsData[teamSelected].skillset;
for(var i = 0; i < skills.length; i++) {
skillsRequired = skills[i];
alert(skillsRequired);
}
}
Am having the data as
var response = '[{"id":1,"name":"Web Demo"},{"id":2,"name":"Audio Countdown"},{"id":3,"name":"The Tab Key"},{"id":4,"name":"Music Sleep Timer"}]';
var obj = JSON.parse(response);
So how I can add the list items dynamically so in future if the list items in the backend increases they should be added directly and how can link dynamic and static elements.
Thanks
Use js appendChild to append each item in your html like this...
var response = [{"id":1,"name":"Web Demo"},{"id":2,"name":"Audio Countdown"},{"id":3,"name":"The Tab Key"},{"id":4,"name":"Music Sleep Timer"}] ;
for (i = 0; i < response.length; i++)
{
var node = document.createElement("LI"); // Create a <li> node
var textnode = document.createTextNode(response[i].name); // Create a text node
node.appendChild(textnode);
document.getElementById("items").appendChild(node); ///append Item
}
<div id="items"></div>
If you want to change your lists according the the changes in the backend, you should periodically test for that via ajax. You can use setInterval and
XMLHttpRequest for these purposes.
When the new data arrives, you should erase your existing list and add new elements to represent the arrived data dynamically.
setInterval(function(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
populateList(xhttp.responseText); //This is your function to create the list
}
};
xhttp.open("GET", "http://www.mybackend.com/list", true);
xhttp.send();
})
And you can use document.createElement function to create a series of elements to represent your data.
function populateList(data) {
var obj = var obj = JSON.parse(response);
document.getElementById('myUl').remove(); //Delete the existing list
var myUi = document.createElement('ul'); //Add new list
obj.forEach(item) {
var listItem = document.createElement('li');
myUi.appendChild(li);
//Then add li details here
}
}
This is just rough code. Your can youse Jquery to get this done very shorter than this. You can even use a JS framework like Angular to automate most of these tasks.
If you are storing dynamic data as like static data, use concat
response.concat(dynamicdata);
I'm taking a class on Ajax and this very simple script is throwing an error I don't understand. I keep getting an Uncaught Type Error saying that the appendChild method is not a function.
The function I'm working through is meant to asynchronously load the contents of a text file into a 'p' tag when the link is clicked.
I'm somewhat new to javascript so it's probably something simple I've missed, I'd appreciate any help in understanding what I'm doing wrong.
(function(){
var link = document.getElementsByTagName('a')[0];
link.onclick = function(){
//create xhr object
var xhr = new XMLHttpRequest();
// handle the "onreadystatechange" event
/*
xhr.readysState property values
0 = Uninitialized
1 = Loading
2 = Loaded
3 = Interactive - server is sending a response
4 = Complete
*/
xhr.onreadystatechange = function() {
if ( (xhr.readyState == 4) && (xhr.status == 200 || xhr.status == 304) ) {
xhr.responseText;
var body = document.getElementsByTagName('body')[0];
var p = document.getElementsByTagName('p');
var pText = document.createTextNode(xhr.responseText);
console.log(p);
console.log(pText);
p.appendChild(pText);
body.appendChild(p);
}
};
// open the request
/* arguments:
1. type of request a (GET or POST)
2. path
3. asynchronaus request? (true || false)*/
xhr.open('GET', 'files/ajax.txt', true);
// send the request
xhr.send(null)
return false; // disable default behavior of link
};
})();
I've created a jsFiddle to show my code:
http://jsfiddle.net/scottm1164/656edjsf/
getElementsByTagName returns a NodeList. Therefore, you have to access individual items with an index like
var p = document.getElementsByTagName('p')[0];
The reason it was giving you
p.appendChild is not a function
is because appendChild is not a function of type NodeList
p is a NodeList; I think you meant document.createElement rather than document.getElementsByTagName.
var p = document.createElement('p');
p is an array of elements. You should select just one. In your fiddle, you don't even have 1.
I am trying to send a JSON object to a web api, but am having a bit of trouble. Its supposed to take value from an input, check the response first, and if the response is correct, send the data. Here is my JS code:
var form = document.getElementById("inputForm"), master = {}, xhr = new XMLHttpRequest(); //global variables used for checking different parts of the process
form.onsubmit = function (e) {
// stop the regular form submission
e.preventDefault();
// collect the form data while iterating over the inputs
var data = {};
for (var i = 0, ii = form.length; i < ii; ++i) {
var input = form[i];
if (input.name) {
data[input.name] = input.value;
}
master.data = data;
}
// construct an HTTP request
function get(url, callback) {
xhr.open("GET", url);
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
var type = xhr.getResponseHeader("Content-Type");
if (type.indexOf("xml") !== -1 && xhr.responseXML)
callback(xhr.responseXML);
else if (type === "application/json")
callback(JSON.parse(xhr.responseText));
else
callback(xhr.responseText);
}
};
// send the collected data as JSON
console.log(JSON.stringify(master));
xhr.send(JSON.stringify(master));
}
get("http://example.com:12321/data");
};
However, when sending it, I get a HTTP 500 error in the console, and the output in the server itself says:
Processing request on /data
Caught error: <unspecified file>(1): expected object or array
And here is the result of the console.log:
{"data":{"val":"2"}}
I thought I was sending the data correctly, but it isnt recognizing it. The example they gave was of a .json file and that works fine, but my stringified JSON isnt working.
Any help would be greatly appreciated