Continuing to develop my first web-service, faced a new problem...
I have a javascript function, which is provide a JSON object as array.
function RequestData(i){
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getitemID='+i, true);
xhr.send();
xhr.onreadystatechange = function() { // (3)
if (xhr.readyState != 4) return;
if (xhr.status != 200) {
alert(xhr.status + ': ' + xhr.statusText);
} else {
alert(xhr.responseText);
var jsonData = JSON.parse(xhr.responseText);
for (var j=0; j< jsonData.length; j++ ){
alert(jsonData[j].name);
}
}
}
xhr.close();
}
there is an array with entities in jsonData like "name", "description", etc
The question is, how can i display a resulting JSON array on the html body of the page? like in foror foreach cycle
need just a simple example. imagine this how the JS file make the content of page
var contentString = '<div id="content">'+
'<div id="bodyContent">'+
'<button onclick="RequestData('+i+')">Load Data!</button>'+
'</div>'+
'</div>';
i want to insert a result from RequestData() function into the content of variable "var contentString"
You should probably use a callback here.
function RequestData(i, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getitemID='+i, true);
xhr.send();
xhr.onreadystatechange = function() { // (3)
if (xhr.readyState != 4) return;
if (xhr.status != 200) {
alert(xhr.status + ': ' + xhr.statusText);
} else {
// pass the parsed data as the parameter of the callback
callback(JSON.parse(xhr.responseText));
}
}
xhr.close();
}
// i is the id we're passing into the function
// and that is used in the xhr.open command
// this is an example
var i = 23;
// i gets passed in as the first parameter,
// the json gets passed as the second parameter to the callback
RequestData(i, function (json) {
// we create a little template using an array
var tmpl = [
'<div id="content"><div id="bodyContent">',
'<button onclick="RequestData(#name)">Load Data!</button></div></div>'
].join('');
var body = document.querySelector('body');
for (var i = 0, l = json.length; i < l; i++) {
// replace the name in the template with the json name for that index
var html = tmpl.replace('#name', json[i].name);
// use insertAdjacentHTML to add that HTML string to the body element
body.insertAdjacentHTML('afterbegin', html);
}
});
You can read more on the widely supported insertAdjacentHTML on the MDN page (it's the first I've heard of it!). And here's an example of it working.
for (var j=0; j< jsonData.length; j++ ){
GetHTML(j);
}
function GetHTML(j) {
var divwrapper = document.CreateElement('div');
var innerdivwrapper = document.CreateElement('div');
var textnode = document.createTextNode("my Name :" + j.Name + 'desc' + j.Description);
innerdivwrapper.appendChild(textnode);
divwrapper.appendChild(innerdivwrapper);
document.getElementsByTagName('body').appendChild(divwrapper);
}
Related
I have an xhttp GET request to fetch the items in my db using its api gateway url. The request works fine as I can see my db's contents which are in string (key:value pairs) from the browser's dev console. Where I'm drawing a blank in is how to pass the db's contents to another function that parses it into javascript objects.
Fetch request code
function fetch(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
}
};
xhttp.open("GET", "<mygatewayapi_url>", true);
xhttp.send();
}
Code for parsing db contents into javascript object
function displayObj(dataStr){
var obj = JSON.parse(dataStr);
var html = "";
var item =;
//var keys = Object.keys(obj);
//var last = keys[item.length - 1];
for (item in obj){
html += '<li>' + item + ' ' + obj[item] + </li>';
/*if (last === true)
html += '<li>' + item + ' ' + obj[item] + </li>' + "<br>";*/
}
return '<li>'+html+'</li>';
You may handle the result in the xhttp.onreadystatechange callback:
function fetch(){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var result = displayObj(this.responseText);
console.log("result: \n", result);
document.getElementById("demo").innerHTML = result;
}
};
xhttp.open("GET", "https://api.github.com/emojis", true);
xhttp.send();
}
function displayObj(dataStr){
var obj = JSON.parse(dataStr);
var html = "";
for (var item in obj){
html += '<li>' + item + ' ' + obj[item] + '</li>';
}
return '<ul>'+html+'</ul>';
}
fetch();
<div id="demo"></div>
I am new to APIs and I want to add the USDA Nutrients database api to my website. I want the user to be able to search for the food,select one of the appeared results and see its' nutrition information.
How can I do this in plain JS? I've created a search bar in my website and JS takes the input and requests the data from the USDA api.
var apiKey = '';
var q = "eggs";
var url = "http://api.nal.usda.gov/ndb/search/?format=json&q=" + q + "&sort=n" + "&max=25" + "&offset=0" + "&api_key=" + apiKey;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
var data = JSON.parse(this.responseText);
document.querySelector("#usdaResults").innerHTML = data.body;
}
};
xhr.send();
I want first to present to the user a list of the results of what they searched. Then after they click the food, I want to present its' nutritional information(protein etc).
EDIT: When a user searches a food, I want to display the "group" , "name"and "manu" of all available results. At the same time,when a user wants to see the nutrition information for a specific food of those listed, I want to get its' "ndbno" number and look into the USDA database for it so I can display the data after. Same way as displayed in the official website: https://ndb.nal.usda.gov/ndb/search/list?SYNCHRONIZER_TOKEN=c91f87b5-59c8-47e0-b7dc-65b3c067b7ff&SYNCHRONIZER_URI=%2Fndb%2Fsearch%2Flist&qt=&qlookup=egg+potato&ds=&manu=
EDIT2: I'm getting this error now.
var apiKey = '';
var q = document.getElementById('search').value;
var url = "http://api.nal.usda.gov/ndb/search/?format=json&q=" + q + "&sort=n" + "&max=25" + "&offset=0" + "&api_key=" + apiKey;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
function getData() {
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
var data = JSON.parse(this.responseText);
if (data && data.list && data.list.item) {
var html = "";
data.list.item.map(item => {
let string = "<p>Name: " + item.name + " Manu: " + item.manu + " Group: " + item.group + "<p>";
html += string;
})
}
document.querySelector("#usdaResults").innerHTML = html;
}
else {
console.log("Error", xhr.statusText);
}
}
xhr.send();
}
HTML:
<section class="usda">
<h1>USDA Nutrients Database</h1>
<form id="search">
<input type="text" placeholder="Search.." name="search">
<button type="button" onclick="getData();">Search</button>
</form>
<div id="usdaResults"></div>
</section>
So, it may be that there are errors with your XHR call - however we can catch and log those errors. You want to open your developer tools in your browser (usually right click > developer tools) to look at the JS logs.
I'm getting: VM131:20 GET http://api.nal.usda.gov/ndb/search/?format=json&q=eggs&sort=n&max=25&offset=0&api_key= 403 (Forbidden)
But that's because I have no API Key. If you do not, you'll need to get an API key from them.
I have grabbed some code from another SO post, here:
var apiKey = '';
var q = "eggs";
var url = "http://api.nal.usda.gov/ndb/search/?format=json&q=" + q + "&sort=n" + "&max=25" + "&offset=0" + "&api_key=" + apiKey;
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function (oEvent) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText)
} else {
console.log("Error", xhr.statusText);
}
}
};
xhr.send();
Reference:
XMLHttpRequest (Ajax) Error
EDIT:
For the response, once you have parsed the JSON - you can get all the available name, group and manu of the data as so - I've output the details in tags, and this is untested - so maybe incorrect, but this is more for pseudo code.
var data = JSON.parse(this.responseText);
//Assuming data is valid!
if (data && data.list && data.list.item) {
var html = "";
data.list.item.map(item => {
let string = "<p>Name: " + item.name + " Manu: " + item.manu + " Group: " + item.group + "<p>";
html += string;
})
}
document.querySelector("#usdaResults").innerHTML = html;
I have a Java REST API, with some JSOn data, that I'm working with, in javascript.
I have two methods one to show data, and when to add new data:
so I have added an EventListener to my first bata to submit data:
btn.addEventListener("click", function() {
var request = new XMLHttpRequest();
request.open('GET', 'http://localhost:8084/RestandJson/api/Person');
request.onload = function(){
var data = JSON.parse(request.responseText);
addPerson(data);
};
request.send();
});
with the addPerson method like this:
const addPerson = (data) => {
var fName = document.getElementById("fname").value;
var lName = document.getElementById("lname").value;
var age = document.getElementById("age").value;
var id = data[data.length-1].id +1;
const person = {fName, lName, age, id};
data.push(person);
console.log(person);
for(i = 0; i< data.length; i++){
console.log(data[i]);
}
}
the problem is, that new data is generated for each GET request, so I only want to fetch the data once, and save that in an array, and then add new persons from there on.
I have a method to show the JSON data as well after converting it into objects:
I added an event listener to another button like before where I'm calling this method:
render HTML = (data) => {
let htmlString = "";
for(i = 0; i < data.length; i++){
htmlString += "<p> " + data[i].fName +" " + " " + data[i].lName + " " + data[i].age + " " + data[i].id + "</p>"
}
root.insertAdjacentHTML('beforeend', htmlString);
}
//bind click event on button to add person info
addPersonbtn.addEventListener('click', function() {
addPerson();
});
// fetch all person data from api (call this function when app load)
function getPersonList() {
var request = new XMLHttpRequest();
request.open('GET', 'http://localhost:8084/RestandJson/api/Person');
request.onload = function(){
var data = JSON.parse(request.responseText);
renderHTML(data);
};
request.send();
}
function postPersonData(personInfo) {
// your api to add single persion info
// on success call getPersonList(), it will update the list
}
const addPerson = () => {
var fName = document.getElementById("fname").value;
var lName = document.getElementById("lname").value;
var age = document.getElementById("age").value;
//var id = data[data.length-1].id +1; // handle it on db side, Primary key, auto generation
const person = {fName, lName, age};
postPersonData(person);
}
renderHTML = (data) => {
let htmlString = "";
for(i = 0; i < data.length; i++){
htmlString += "<p> " + data[i].fName +" " + " " + data[i].lName + " " + data[i].age + " " + data[i].id + "</p>"
}
root.insertAdjacentHTML('beforeend', htmlString);
}
i have made pseudo code for you , hope it will helps you a little bit
I 've got a simple thing:
There's a JSON with books objects,every book has a title,author and year.
I would like to choose one option from the list and display chosen property in a table.I've used an example from W3 but right now i'm stuck and nothing works as it should...
Link's here
function change_myselect(sel) {
var obj, dbParam, xmlhttp, myObj, x, txt = "";
obj = { "table":sel, "limit":20 };
dbParam = JSON.stringify(obj);
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
myObj = JSON.parse(this.responseText);
txt += "<table border='1'>"
for (x in myObj) {
txt += "<tr><td>" + myObj[x].name + "</td></tr>";
}
txt += "</table>"
document.getElementById("demo").innerHTML = txt;
}
};
xmlhttp.open("GET", "generated.json", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("x=" + dbParam);
}
The problem is quite easy to spot with a debugger line
console.log(myObj)
It is an object and you are trying to loop over it. You want to be looping over the key in the object that holds the array.
console.log(myObj.books);
You are iterating over a single property books in an object instead of iterating over the array that property contains.
Instead of this:
for (x in myObj) {
txt += "<tr><td>" + myObj[x].name + "</td></tr>";
}
try something like this:
myObj.books.forEach((book) => {
txt += "<tr><td>" + book[sel.toLowerCase()] + "</td></tr>";
});
I tried to run this but it doesn't work.
It is intended to return a variable assigned inside a function, that was passed as callback to sendRequest(), which is retrieving data from the Internet through XMLHttpRequest asynchronously.
Can anyone tell me why this is not working and always returning ""?
function sendRequest(requestCode, args, callback){
var req = requestEngineUrl + "?req=" + requestCode + ";" + args;
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function(){
if(xmlHttp.readyState == 4)
{
if(callback != null){
callback(xmlHttp.responseText);
}
}
};
xmlHttp.open("GET", req, true);
xmlHttp.send(null);
}
this.assembleProcess = function(){
if(!isNull(this.id) && !isNull(this.titles)){
var titles = this.titles;
var id = this.id;
c = "";
sendRequest('304', id,
function(result){
var res = result.split("/");
var title = res[0];
var possibilities = res[1];
var fcontent = title + '<br><div>';
if(titles.length != possibilities){
console.log("WARNING: [SURVEYCARD].titles has not the same length as possibilities");
}
for(i = 0; i < possibilities; i++){
fcontent += '<div><a onclick="sendRequest("301",' + id + ',' + i + ',null)">' + titles[i] + '</a></div>';
}
fcontent += '</div>';
c = fcontent;
});
return c;
}
As an XMLHttpRequest is async, you should write an async function for that matter, like this
this.assembleProcess = function(callback){
if(!isNull(this.id) && !isNull(this.titles)){
var titles = this.titles;
var id = this.id;
c = "";
sendRequest('304', id,
function(result){
var res = result.split("/");
var title = res[0];
var possibilities = res[1];
var fcontent = title + '<br><div>';
if(titles.length != possibilities){
console.log("WARNING: [SURVEYCARD].titles has not the same length as possibilities");
}
for(i = 0; i < possibilities; i++){
fcontent += '<div><a onclick="sendRequest("301",' + id + ',' + i + ',null)">' + titles[i] + '</a></div>';
}
fcontent += '</div>';
c = fcontent;
callback(c)
});
}
and then, instead of using this.assembleProcess as a function with a result, you should pass a function as parameter:
Instead of
console.log(this.assembleProcess);
do this
this.assembleProcess(function(c){console.log(c)});