I have a JSON file with numerous entries. Below is just 2 of them.
{
"layers": [
{
"name": "Test1",
"id": "Feature",
"subject": "General"
},
{
"name": "Test2",
"id": "Feature",
"subject": "General"
}
]
}
When I run this script and all checkboxes are rendered ok. When I click one of them, I get the output at the console as [object,Object]. Can't see any of properties. I tried the JSON.stringify but no success. Ideas? Thanks.
function XX(){
var mydata = JSON.parse(data)
subjects = []
for (var i = 0; i < mydata.layers.length; i++) {
theID = mydata.layers[i].name
subjects[i] = mydata.layers[i].subject
if (!thecontent[subjects[i]]) {
thecontent[subjects[i]] = '<input type="checkbox" id="' + theID + '" onclick=\'window.loadFL("' + mydata.layers[i] + '")\'>'
} else {
thecontent[subjects[i]] += '<input type="checkbox" id="' + theID + '" onclick=\'window.loadFL("' + mydata.layers[i] + '")\'>'
}
thecontent[subjects[i]] += '<label for="' + theID + '"> ' + mydata.layers[i].name +
'</label><br>'
}
for (k = 0; k < subjects.length; k++) {
document.getElementById(subjects[k]).innerHTML = thecontent[subjects[k]] + '<br>'
}
}
}
window.loadFL = function (theresponse) {
console.log(theresponse);
}
When you do this:
thecontent[subjects[i]] += '<input type="checkbox" id="' + theID + '" onclick=\'window.loadFL("' + mydata.layers[i] + '")\'>'
or let me mod it into a simpler form, for ease of discussion:
const myInput = '<input onclick=\'loadFL("' + myObject + '")\'>'
You’re concatenating object to string with + operator. That’ll type-cast object into string type, by implicitly calling myObject.toString() method (inherited from Object.prototype) which will return the string "[object,Object]".
So if you console.log(myInput), you’ll see this:
<input onclick='loadFL("[object, Object]")' >
Above is the explanation.
Below is solution.
If you only need to pass the JSON string value to loadFL. You can do:
const myInput = '<input onclick=\'loadFL(' + JSON.stringify(JSON.stringify(myObject))+ ')\'>'
You read it right, remove the double quotes " in the string, and use JSON.stringify twice.
But if you need to pass the object value, there’s no easy way using HTML string. I’d suggest you use JavaScript to add event listener to HTML node.
If JSON.stringify() doesn't work, you can try to print the index of layers like this:
// some code
thecontent[subjects[i]] = '<input type="checkbox" id="' + theID + '" onclick=\'window.loadFL("' + i + '")\'>'
// some code
window.loadFL = function (layers_index) {
console.log(mydata.layers[layers_index]);
}
Related
I´m populating webpage with sharepoint so I do a json to get data with ajax like these:
function completeFleet(data, target, eng) {
var items = data.d.results;
console.log(items);
var prefix = "<div class='row'>";
var sufix = "</div>";
var menu = "<div class='col-md-4'>";
var cat = "";
var spec = "";
var counter = 0;
var obj = null;
for (item in items) {
spec = "";
if (counter == 1) {
menu += "</div><div class='col-md-4'>";
counter = 0;
}
if (eng) {
obj = JSON.parse(items[item].Specifications);
for (var key in obj) {
spec += "<div class='row'><div class='col-md-12 ftBottomSeparator'><span class=' t10'>" + key + "</span> <span class='t06' style='float:right;'>" + obj[key] + "</span></div></div>";
}
menu += "<div class='row ftContainerOut'><div class='col-md-12 ftContainer'><div class='row ftHeader'><div class='col-xs-9 t09'>" + items[item].Title + "</div><div class='col-xs-3 text-right'></div></div><div class='row'><div class='col-md-6' style='padding-top:10px'><img src='" + items[item].Imagen.Url + "' class='img-responsive img-center' style='border:0px solid blue; max-width:150px;max-height:120px;' /></div><div class='col-md-6'>" + spec + "</div></div></div></div>";
} else {
obj = JSON.parse(items[item].Especificaciones);
for (var key in obj) {
spec += "<div class='row'><div class='col-md-12 ftBottomSeparator'><span class=' t10'>" + key + "</span> <span class='t06' style='float:right;'>" + obj[key] + "</span></div></div>";
}
menu += "<div class='row ftContainerOut'><div class='col-md-12 ftContainer'><div class='row ftHeader'><div class='col-xs-9 t09'>" + items[item].Title + "</div><div class='col-xs-3 text-right'></div></div><div class='row'><div class='col-md-6' style='padding-top:10px'><img src='" + items[item].Imagen.Url + "' class='img-responsive img-center' style='border:0px solid blue; max-width:150px;max-height:120px;' /></div><div class='col-md-6'>" + spec + "</div></div></div></div>";
}
counter++;
}
$(target).html("<div class='panel-body'><div class='container-fluid'>" + prefix + menu + sufix + "</div></div>");
}
I have 5 objects different, but one of these don´t show data, my webpage is in english and spanish, in english it charge all data, but in spanish one of these
doesn´t works and I get error at position 36, and position 36 is the item don´t show. Any idea what is wrong here? Regards
These one works
and this no works
---------Update------------
If I comment this line:
//obj = JSON.parse(items[item].Especificaciones);
and put
if(items[item].Especificaciones){
JSON.parse(items[item].Especificaciones);
}
it now runs with image, but now I don´t have my "Especificaciones" lists
Now when I use
var stringifyObj = JSON.stringify(items[item].Especificaciones);
var obj = JSON.parse(stringifyObj);
I get something like these:
make sure value is not null for the corresponding key inside JSON.parse. For example-
JSON.parse(items[item].Specifications)
make sure items have value in item index and items[item] has the property Specifications.
you can check if items[item].Specifications is not null before JSON.parse.
if(items[item].Specifications){
JSON.parse(items[item].Specifications)
}
Update
JSON.parse() is used to convert a string containing JSON notation into a Javascript object. To be valid JSON, strings must be in double quotes.
Try stringify the object and then parse again.
var stringifyObj = JSON.stringify(items[item].Especificaciones);
var obj = JSON.parse(stringifyObj);
The reason for the error is that JSON.parse() expects a String value and items[item].Especificaciones is an Array
"Eslora":100 pies"
You should probably opening the quotes when you start writing a string value
Situation : I receive JSON array from jQuery <-> PHP Ajax request. Here's structure of unparsed JSON aray :
{"Focus":{"id":2,"brand":"Ford","name":"Focus"}}
And after using JSON.parse(json); the structure looks like :
Focus: Object
brand: "Ford"
id: 2
name: "Focus"
Problem : I want to access all array's '1st tier' elements and use them like an object, but none of the following ways works :
for (var entity in dataTable)
{
formattedText += entity['brand'] + " " + entity['name'] + "<br>";
OR
formattedText += entity.brand + " " + entity.name + "<br>";
OR
formattedText += dataTable[0]['brand'] + " " + dataTable[0]['name'] + "<br>";
}
Any solutions how to read values of all object in this array?
The for..in loop uses keys and does not return the elements themself: for (var key in dataTable)You would then access each element with dataTable[key]. The key is actually the name of the Element.
You where using it as you would use a for..of loop, but that is a new feature not supported in all Browsers yet.
Demo:
var dataTable = {"Focus":{"id":2,"brand":"Ford","name":"Focus"}}
var formattedText = ""
for (var key in dataTable)
{
formattedText += dataTable[key]['brand'] + " " + dataTable[key]['name'] + "<br>";
}
document.write(formattedText)
Object.keys will return array of all the keys of the object
You can loop(forEach/for-loop) through the keys to get the expected output.
Using forEach:
var dataTable = {
"Focus": {
"id": 2,
"brand": "Ford",
"name": "Focus"
}
}
var keys = Object.keys(dataTable);
var str = '';
keys.forEach(function(item) {
str += dataTable[item].brand + " " + dataTable[item].name;
});
alert(str);
Using for-loop:
var dataTable = {
"Focus": {
"id": 2,
"brand": "Ford",
"name": "Focus"
}
}
var keys = Object.keys(dataTable);
var str = '';
for (var i = 0, len = keys.length; i < len; i++) {
str += dataTable[keys[i]].brand + " " + dataTable[keys[i]].name;
}
alert(str);
The correct syntax to write this would be:
When you loop, you'll get the key name in the variable entity and then use that to get the value, also, you need to access the associative array inside the first key i.e. Focus
var dataTable = JSON.parse('{"Focus":{"id":2,"brand":"Ford","name":"Focus"}}');
var formattedText = '';
for (var entity in dataTable.Focus) {
formattedText += dataTable.Focus['brand'] + " " + dataTable.Focus['name'] + "<br>";
}
Sounds like you're using each function in a wrong way. in your each function change arguments to key and value like this:
$.each(dataTable, function (key, value) {
//access key and values here
});
In your case u should iterate again over key and values of your key values.
EDITED:
I'm (still) having a little trouble getting values from a nested array in JSON and appending them to generated html.
I'm currently using the following JSON (updated):
{
"OuterArray": [
{
"memberId": "01",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "02",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "03",
"key01": "",
"included": "false",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
},
{
"memberId": "04",
"key01": "",
"included": "true",
"nestedArray": [
{ "keyA": "", "keyB": "" },
{ "keyA": "", "keyB": "" }
]
}
]
}
And this js:
for (var i = 0; i < outerArray.length; i++) {
if (outerArray[i].included !== "false") {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
// etc.
var nestedArray = outerArray[i]["nestedArray"];
myDiv.innerHTML +=
"<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ "<div class=\"nested-array-stuff\">" // help?
+ "</div>"
+ "</div>"
var nestedArrayStuff = document.getElementsByClassName("nested-array-stuff")[i];
for (var j=0; j<outerArray.length; j++) {
nestedArrayStuff.innerHTML += "<p class=\"keyA\">" + nestedArray[j].keyA + "</p>";
}
}
Note that one of the keys in the outer array has a boolean value which determines whether or not it (the outer array member) is - and its nested array stuff are - included in the page.
So just to reiterate, the goal is:
<div class="outer-array-stuff">
<!-- <snip: some outer array key/values here /> -->
<div class="nested-array-stuff">
<div class="nested-array-stuff">
<p>[e.g., nested array key 1 value]</p>
<p>[e.g., nested array key 2 value]</p>
<p>[etc.]</p>
</div>
</div>
If all the outer array members 'included' are 'true', everything outer & nested loads, but this is not exactly what I want; I need to filter so that only those 'included' !== "false". So now my problem is that despite being inside the if 'included'/else loop, the outer array members stop loading at the first excluded outer array member (actually, the next 'true' outer array member does load, but its nested array stuff doesn't, and then nothing further loads, the entire outer array loop dies.
Any insight as to why this is happening?
Many thanks to dreyescat for the help to this point.
P.S. generally I'm trying to minimize my reliance on jQuery.
Many thanks, svs
You are almost there. Here is your code revised with some comments.
// Generally is not a good practice iterate arrays using for..in
//for (var i in outerArray) {
for (var i = 0; i < outerArray.length; i++) {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
// This should by outerArray array and not jsonData object.
var nestedArray = outerArray[i]["nestedArray"];
myDiv.innerHTML +=
"<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ "<div class=\"nested-array-stuff\">" // help?
+ "</div>"
+ "</div>"
// getElementsByClassName gets a list of elements that have that class.
// I suppose you want to add the elements to the corresponding outer array.
// Let's use the loop index i to get the proper parent element. You could also
// just get the last one.
var nestedArrayStuff = document.getElementsByClassName("nested-array-stuff")[i]; // help?
// Again I recommend you not to use for..in for arrays.
for (var obj in nestedArray) {
nestedArrayStuff.innerHTML += "<p class=\"keyA\">" + nestedArray[obj].keyA + "</p>"; // NOPE
}
}
See demo.
You could also build the entire nested array stuff before adding it to the div element. Then you don't need to query the document to get the nested array stuff element.
for (var i in outerArray) {
var key01 = outerArray[i].key01;
var key02 = outerArray[i].key02;
var nestedArray = outerArray[i]["nestedArray"];
var nestedArrayStuff = '<div class=\"nested-array-stuff\">';
for (var obj in nestedArray) {
nestedArrayStuff += "<p class=\"keyA\">" + nestedArray[obj].keyA + "</p>"; // NOPE
}
nestedArrayStuff += '</div>';
myDiv.innerHTML += "<div class=\"outer-array-stuff\">"
+ "<p class=\"key01\">" + key01 + "</p>"
+ "<p class=\"key02\">" + key02 + "</p>"
+ nestedArrayStuff
+ "</div>"
+ "</div>";
}
See demo
nestedArray is not a string. your nestedArray array loop should be as follows.
var nestedArray = outerArray[i].nestedArray;
for (var j in nestedArray) {
console.log(nestedArray[j].keyA);
console.log(nestedArray[j].keyB);
}
Here is your complete solution, I used lists to output content. It assumes we have one container:
<div id="mydiv"></div>
Than JS would be:
var myDiv = document.getElementById('mydiv');
var outerArray = [
{
"memberId":"01",
"key01":"",
"key02":"key02 exists, ...",
"included":"true",
"nestedArray":[
{
"keyA":"1",
"keyB":"2"
},
{
"keyA":"3",
"keyB":"4"
}
]
},
{
"memberId":"02",
"key01":"key01 value..",
"included":"true",
"nestedArray":[
{
"keyA":"5",
"keyB":""
},
{
"keyA":"",
"keyB":"8"
}
]
},
{
"memberId":"03",
"key02":"",
"included":"false",
"nestedArray":[
{
"keyA":"",
"keyB":"9"
},
{
"keyA":"",
"keyB":""
}
]
},
{
"memberId":"04",
"key01":"value of key01",
"key02":"key02 value ...",
"included":"true",
"nestedArray":[
{
"keyA":"",
"keyB":"10"
},
{
"keyA":"11",
"keyB":"12"
}
]
}
];
var insertHtml = '';
for (var i = 0; i < outerArray.length; i++) {
if (outerArray[i].included !== "false") {
insertHtml += "<ul class=\"outer-array-stuff\">";
insertHtml += " <li>";
insertHtml += " <p class=\"memberId\">memberId(" + i + "): " + outerArray[i].memberId + "</p>"
insertHtml += " <p class=\"key01\">key01: " + ( ( typeof outerArray[i].key01!='undefined' && outerArray[i].key01 ) ? outerArray[i].key01 : '') + "</p>"
insertHtml += " <p class=\"key02\">key02: " + ( ( typeof outerArray[i].key02!='undefined' && outerArray[i].key02 ) ? outerArray[i].key02 : '') + "</p>"
var nestedArray = outerArray[i]["nestedArray"];
if ( nestedArray.length>0 ) {
insertHtml += " <ul class=\"nested-array-stuff\">"
for (var j=0; j<nestedArray.length; j++) {
insertHtml += "<li class=\"keyA\">keyA(" + j + "): " + nestedArray[j].keyA + "</li>";
insertHtml += "<li class=\"keyB\">keyB(" + j + "): " + nestedArray[j].keyB + "</li>";
};
insertHtml += " </ul>"
};
insertHtml += " </li>";
insertHtml += "</ul>"
}
}
myDiv.innerHTML = insertHtml;
Basically, I'm using JavaScript to dynamically generate a form that allows from multiple entries within a single submission. Here's the code I'm using for that:
function addEvent()
{
var ni = document.getElementById('myDiv');
var numi = document.getElementById('theValue');
var num = (document.getElementById('theValue').value - 1) + 2;
numi.value = num;
var divIdName = 'my' + num + 'Div';
var newdiv = document.createElement('div');
newdiv.setAttribute('id', divIdName);
newdiv.innerHTML = '<table id="style" style="background-color: #ffffff;"><tr><td colspan="2">Entry ' + num + '<hr \/><\/td><\/tr><tr><td><label>Item 1: <\/td><td><input name="item1_' + num + '" value="" type="text" id="item1" \/><\/label><\/td><\/tr><tr><td><label>Item 2: <\/td><td><input name="item2_' + num + '" type="text" id="item2" \/><\/label><\/td><\/tr><tr><td><label>Item 3: <\/td><td><input type="text" name="item3_' + num + '" id="item3" \/><\/label><\/td><\/tr><tr><td><label>Item 4: <\/td><td><select name="item4_' + num + '" id="item4"><option value="---">---<\/option><option value="opt_1">1<\/option><option value="opt_2">2<\/option><option value="opt_3">3<\/option><option value="opt_4">4<\/option><\/select><\/label><\/td><\/tr><\/table>';
ni.appendChild(newdiv);
}
This works just fine, generating the entries fields I need. Using console in-browser, I've even verified all the names are correct. The issue is that I need to then take the selections and generate output. I've tried several methods, but everything resulted in null values.
function generateVideo()
{
var entries = document.getElementById('theValue').value;
var item1 = {};
var item2 = {};
var item3 = {};
var item4 = {};
for(i = 1; i <= entries; i++)
{
item1[i - 1] = document.getElementById('item1_' + i);
item2[i - 1] = document.getElementById('item2_' + i);
item3[i - 1] = document.getElementById('item3_' + i);
item4[i - 1] = document.getElementById('item4_' + i);
}
var code = 'Copy code and paste it into Notepad<br \/>"Save as" filename.html<br \/><textarea name="" cols="45" rows="34">header template\n';
for(i = 0; i < entries; i++)
{
if(i != (entries - 1))
{
code = code + ' ["' + item1[i] + '", "' + item2[i] + '", "' + item3[i] + '", "' + item4[i] + '"],\n';
}
else
{
code = code + ' ["' + item1[i] + '", "' + item2[i] + '", "' + item3[i] + '", "' + item4[i] + '"]\n';
}
}
code = code + 'footer template<\/textarea>';
var result = document.getElementById("result");
result.innerHTML = code;
}
The output is as follows:
Copy code and paste it into Notepad<br />"Save as" CourseName_Unit_Chapter.html<br /><textarea name="" cols="45" rows="34">header template
["null", "null", "null", "null"]
footer template</textarea>
Now, certain fields can be null, that's fine (I'll do form validation after I get it working), but I'm getting null for every field regardless of what is entered.
I, originally, had the .value on the getElementByIds, but that only results in the script not running when the entries variable is greater than 0 (default), which is why I tried removing them.
function generateVideo()
{
var entries = document.getElementById('theValue').value;
var item1 = {};
var item2 = {};
var item3 = {};
var item4 = {};
for(i = 1; i <= entries; i++)
{
item1[i - 1] = document.getElementById('item1_' + i).value;
item2[i - 1] = document.getElementById('item2_' + i).value;
item3[i - 1] = document.getElementById('item3_' + i).value;
item4[i - 1] = document.getElementById('item4_' + i).value;
}
var code = 'Copy code and paste it into Notepad<br \/>"Save as" filename.html<br \/><textarea name="" cols="45" rows="34">header template\n';
for(i = 0; i < entries; i++)
{
if(i != (entries - 1))
{
code = code + ' ["' + item1[i] + '", "' + item2[i] + '", "' + item3[i] + '", "' + item4[i] + '"],\n';
}
else
{
code = code + ' ["' + item1[i] + '", "' + item2[i] + '", "' + item3[i] + '", "' + item4[i] + '"]\n';
}
}
code = code + 'footer template<\/textarea>';
var result = document.getElementById("result");
result.innerHTML = code;
}
I've also tried variations of multidimensional arrays, instead of four arrays, but got the same results.
The output, as indicated by the removal of the .value on the getElementByIds, is good. Basically, there is something wrong with my attempts to populate the arrays using the dynamically generated forms.
I suspect that the issue with the declaration of the element ID, but I'm not sure how else to declare it. This style of scripting is not my norm. ^^'
Anyone have any ideas on how to fix the for loop to generate the array?
replace all occurences of
itemN[i]
with
itemN[i].value
if that doesnt work add
console.log( itemN[i] )
and see what it outputs
I'm trying to create a for() loop with JSON data that's already been decoded, the problem is adding my loop variable (in this case i), to the end of the element that I'm referencing.
For example, my JSON structure, dumped:
{
"url": "http://www.example.com",
"rid": 1,
"rname": "Apple iPhone 4 Rotation",
"rmin": 90,
"rmax": 150,
"blank": 0,
"geo_country_0": "GB",
"geo_url_0": "http://en",
"geo_country_1": "FR",
"geo_url_1": "http://fr",
"geo_country_2": "ES",
"geo_url_2": "http://es"
}
In the case of geo_country_ and and geo_url_ I need to append a number, in this case the loop variable.
My actual for loop, for a better understanding:
for(i = 1; i < count; i++) {
$('#geo-location').append('<div id="glt_' + i + '" class="clone"><select name="g_country['+i+']" class="glt-input-c">' + options + '</select><input type="text" name="g_url[' + i + ']" class="glt-input-c" value="' + data.geo_url_i+ '"/></div>');
$('select[name="g_country['+i+']"').find('option[value="' + data.geo_country_i+ '"]').attr('selected','selected');
}
So far I've tried:
Encasing the the i like [i].
Escaping it like \i. (This was probably a stupid idea).
Adding a pre-fixing + like, + data.geo_country + i +.
What do I need to do to have i interpreted properly?
Any help would be greatly appreciated!
In JavaScript, you may address an object's properties in two ways:
var value = myobject.myproperty;
var value2 = myobject['myproperty'];
Using this knowledge, you can rewrite your code as follows:
for(i = 1; i < count; i++) {
$('#geo-location').append('<div id="glt_' + i + '" class="clone"><select name="g_country['+i+']" class="glt-input-c">' + options + '</select><input type="text" name="g_url[' + i + ']" class="glt-input-c" value="' + data['geo_url_' + i] + '"/></div>');
$('select[name="g_country['+i+']"').find('option[value="' + data['geo_country_' + i] + '"]').attr('selected','selected');
}
Access it like
data['geo_country_' + i]
And you should have no issues