How to nest table withing table read from json - javascript

I got this json object which its structure similar to this:
vendor have name, phone, fax, contacts
contacts have firstName, lastName, title, phone, email
I have created the first level in the table, but i didn't how to create the second nested level
function getData(vType) {
$.getJSON('/LocalApp/VendorController', {
vendorType : vType,
time : "2pm"
}, function(vendorsJson) {
$('#vendors').find("tr:gt(0)").remove();
var vendorTable = $('#vendors');
$.each(vendorsJson, function(index, vendor) {
$('<tr>').appendTo(vendorTable).append(
$('<td>').text(vendor.name)).append(
$('<td>').text(vendor.phone)).append(
$('<td>').text(vendor.fax)).append(
'<table class="contactTable"><tr><th>First Name</th><th>Last Name</th><th>Title</th><th>Phone</th><th>E-Mail</th></tr></table>');
});
});
}
So how can i add vendor.contacts as a nested table in jQuery code?
i know my code is not clean, jquery is confusing to me compared to Java

Not sure if you want the table in a cell of the vendor or not, but try something like this...
var contactTableHtml = '<table class="contactTable"><tr><th>First Name</th><th>Last Name</th><th>Title</th><th>Phone</th><th>E-Mail</th></tr></table>';
var vendorTableContent = $.map(vendorsJson,function (index, vendor) {
var contactTableContentHtml = $.map(vendor.contacts,function (index, contact) {
return "<tr><td>" + contact.firstName + "</td><td>" + contact.lastName + "</td><td>" + contact.title + "</td><td>" + contact.phone + "</td><td>" + contact.email + "</td></tr>";
}).join("");
return '<tr>' +
'<td>' + vendor.name + '</td>' +
'<td>' + vendor.phone + '</td>' +
'<td>' + vendor.fax + '</td>' +
'<td>' + contactTableHtml + contactTableContentHtml + '</td>' +
'</tr>';
}).join("");
vendorTable.append(vendorTableContent);
First I create a subtable as a string and then add it to the main table. I also suggest to create one big html string and add it once to the DOM. This is a lot quicker then calling $('...') everytime.
PS. Haven't been able to test it, but let me know if you get an error.

Unless you're very constrained for how much you can send with the page (that is, every single K of data counts against you), I don't think jQuery is a good fit for this kind of thing.
I think of JSON + something => HTML as templating, so I usually use a JavaScript templating tool like Handlebars to do that kind of thing. It's a more natural fit. Plus you can try right now with a site like Try Handlebars.js to interactively craft a template that takes some of your sample JSON and output the HTML you desire.
In all likelihood, a {{#each}} with another {{#each}} inside of it could probably handle the conversion of a nested JSON to whatever HTML you're after.

Related

HTML Element not being inserted

I'm working on a .NET Core project for my company where work orders are loaded from our SQL database using Entity Framework, filtered and then displayed as markers on a map through Google Maps API for our installers.
We have two types of filters: one that gets included in an Ajax POST, and one that filters locally to decrease load times and performance issues. What I'm trying to do is load the local filter items (lists that are included in the response when calling the initial Ajax POST). If the list of filter items exceeds 5 items, I want them to collapse to only 5 items and insert an anchor which expands (utilizes jQuery's toggle()) showing the rest of the items in that list.
This is the excerpt from the JavaScript function which takes care of that:
filterItems
.forEach((filterItem, i) => {
var localItem = '<label class="' + selectorContainerClass
+ ' selectorContainer" id="' + selectorContainerIdPrefix + filterItem.key
+ '"><input id="' + convertValToEng(filterItem.value)
+ '" type = "checkbox" class="filled-in navy" name="' + inputName
+ '" value="' + filterItem.key
+ '" onchange="localFilter(this, this.value)" /><span class="selector-value">'
+ filterItem.value
+ '</span> <span id="' + paramName + 'Cnt__' + filterItem.key
+ '" class="selector-count"></span></label ><br />';
document.querySelector("#" + colId).insertAdjacentHTML('beforeend', localItem);
if (i >= 5) {
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key).addClass("collapse");
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key).toggle(100);
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key + " + br").toggle(100);
}
});
if (filterItems.length > 5) {
//TODO: Fix the bug here; the .filter-collapse element is not being inserted under local installers.
var newEl = '<a class="filter-collapse" onclick="toggleFilterExpand(false, this)";><i class="material-icons">expand_more</i></a>';
document.getElementById(colId).insertAdjacentHTML('beforeend', newEl);
}
I should be getting a newEl inserted under the "Installer" column (8 installers, 3 of them not being displayed), but I'm not. I've tried jQuery's after() and insertAfter() methods, but neither of those worked. newEl is being generated for the "Area" column, as it should, but for the "Installer" column it's not.
I've also tried inserting the element manually through the console window with the exact same code and it works.
Would appreciate some help with this as I feel lost regarding this issue.
Thanks.
It turned out to be a stupid mistake on my end where I was removing the element newEl from the all the other filter lists before inserting a new one to the currently iterated one.

Why jQuery append() removes words after first blank space in string

I'm trying to dynamically generate a form after an ajax request. Below is the relevant code sample :
for (var i in response.responseJSON[0].fields) {
var field = response.responseJSON[0].fields[i];
$('#properties_form').append('<label for=' + i + '>' + i + '</label>' +
'<input id=' + i + ' value=' + field + '>');
}
My problem is that, when var i and var field are strings with blank spaces like "Hello world", my label and inputs will be like <label id="Hello" world=""> and <input value="Hello" world="">. However, the label text will be displayed correctly i.e. <label>Hello world</label>.
I've no idea what kind of sorcery that is, but I'll be very grateful for any help. Thanks in advance.
There's a much more robust way of doing this.
for (var i in response.responseJSON[0].fields) {
var field = response.responseJSON[0].fields[i];
$('#properties_form')
.append($('<label>').attr('for', i).text(i))
.append($('<input>').attr('id', i).val(field));
}
You won't have to worry about the content of the strings as jQuery and the DOM will handle it for you. Not to mention this is much easier to read.
Use " to enclose the attributes.
$('#properties_form')
.append('<label for="' + i + '">' + i + '</label>' +
'<input id="' + i + '" value="' + field + '">');
EDIT
This will break for the cases where the value for i is something like This "works". Best solution is to append as jQuery or JS objects rather than using HTML string just like Daniel's answer.
Following snippet contains the correct fix for this. Updated based on the answer from Daniel.
i = 'Hello "World"';
field = 'Hello "World"s';
$('#properties_form')
.append($('<label>').attr('for', i).text(i))
.append($('<input>').attr('id', i).val(field));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="properties_form"></div>

Pull a single item from json and display in html

I have an array in a JSON file and what I want to do is pull a single entry from the array and display it when the page loads.
I have gotten partway there using this question and answer, however my attempt to adapt this answer causes the output html block to repeat the array items in sequence instead of simply picking one.
Here is a screenshot of what I get:
screenshot of output
I am likely doing something real stupid, and I hope someone can point this out.
My script is as follows:
$.getJSON('recommend.json', function(data) {
var entry = data[Math.floor(Math.random()*data.length)];
$.each(data, function(entryIndex, entry) {
var html = '<div class="rec_img"><img src="./recs/' + entry['img'] + '" /></div>';
html += '<span class="rec_title">' + entry['title'] + '</span><p>';
html += '<span class="rec_author">' + entry['author'] + '</span><p>';
html += '<span class="rec_blurb">' + entry['blurb'] + '</span>';
$('#recblock').append(html).fadeIn();
});
});
Any questions just let me know.
Cut this:
$.each(data, function(entryIndex, entry) {
The whole purpose of $.each is to iterate over the entire array, which is the opposite of what you want. You're already defining entry earlier as a random entry from the data.
So you'll have:
$.getJSON('recommend.json', function(data) {
var entry = data[Math.floor(Math.random()*data.length)];
var html = '<div class="rec_img"><img src="./recs/' + entry['img'] + '" /></div>';
html += '<span class="rec_title">' + entry['title'] + '</span><p>';
html += '<span class="rec_author">' + entry['author'] + '</span><p>';
html += '<span class="rec_blurb">' + entry['blurb'] + '</span>';
$('#recblock').append(html).fadeIn();
});

AJAX / JQuery - Print each nested child on new table row

I've been tearing my hair out over this seemingly simple problem, but I can't wrap my head around it.
I'm trying to generate a table in HTML using AJAX and some JQuery. The XML holds the data that I want rendered, each Child Node being rendered on a new line. The AJAX does all of the heavy lifting and generates the table.
XML Code:
<?xml version="1.0" encoding="utf-8"?>
<shows>
<show>
<title>Title</title>
<light>
<rule>Rule 1</rule>
<rule>Rule 2</rule>
</light>
<medium>
<rule>Rule 3</rule>
<rule>Rule 4</rule>
</medium>
<hard>
<rule>Rule 5</rule>
<rule>Rule 6</rule>
</hard>
<extreme>
<rule>Rule 7</rule>
</extreme>
</show>
</shows>
Obviously, I'll have more than this tiny bit of data down but that's besides the point.
Pertinent HTML
<table id="rules"></table>
And the Javascript:
$(xml).find('shows > show').each(function () {
var title = $(this).find('title').text();
title = "<tr>" + "<th>" + "</th>" + "<th>" + "<h1>" + title + "</h1>" + "</th>" + "</tr>";
category = "<tr>" + "<th>" + "</th>" + "<th>" + "Category Title: " + "</th>" + "</tr>";
rule = $(this).find('light > rule').text(); //problem is here?
punish = punish + "<tr>" + "<td>" + ruleCount + "</td>" + "<td>" + rule + "</td>" + "</tr>";
There's much more to the Javascript than this, but the line with the comment above I believe is the culprit of my headache. It's also essentially copied and pasted 3 more times in the script and modified to generate rules for medium, hard and extreme.
Here's the problem:
The Title, Category labels (table headers), rows, cells all generate just fine, but the data needs to be rendered so that each node (rule) is created on a new line (or new table row, essentially). Instead, the rule = $(this).find('light > rule').text(); line is cramming Rule 1 and 2 together, 3 and 4 together, etc (when reused further in the script obviously). The resulting HTML is a bit like this:
<table id="rules">
<tr><th></th><th><h1>Title</h1></th></tr>
<tr><td>1</td><td>Rule1Rule2</td></tr>
</table>
What I really want is for each rule to be on it's own table row. Like this:
<table id="rules">
<tr><th></th><th><h1>Title</h1></th></tr>
<tr><td>1</td><td>Rule1</td></tr>
<tr><td>2</td><td>Rule2</td></tr>
</table>
Any idea what I'm doing wrong??
Thanks in advance.
rule = $(this).find('light > rule').text();
This selects the two rule elements in light. text() returns a concatenation of the text of all elements in the wrapped set. You'll need to iterate over each rule using each()
$(this).find('light > rule').each(function() {
punish += "<tr><td>" + ruleCount + "</td><td>" + $(this).text() + "</td></tr>";
});
You need to use a loop to iterate through each rule
$(this).find('light > rule').each(function () {
punish = punish + "<tr>" + "<td>" + (ruleCount++) +"</td>" + "<td>" + $(this).text() + "</td>" + "</tr>";
})

Create HTML table in Javascript with JSON or jQuery

I'm not any good at JavaScript (yet!) - I really need some help to get past this stuck point that is causing me lots of premature hair loss!
I just can't seem to figure out how to build the following HTML code using JSON data.
This is a sample of the JSON data that I have being generated for the new version of this page I'm working on:
[{"id":"1732","name":"1BR House","checkin":"2012-12-20","checkout":"2012-12-23","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1587","name":1BR House","checkin":"2012-12-23","checkout":"2013-01-01","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1661","name":"2BR Studio","checkin":"2012-12-25","checkout":"2013-01-02","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1829","name":"Studio Cottage","checkin":"2012-12-25","checkout":"2012-12-29","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1787","name":"Studio Cottage","checkin":"2012-12-29","checkout":"2013-01-08","inclean_cleaner":"","inclean_datetime":"2012-12-29 00:00:00","inclean_notes":""},{"id":"1843","name":"1BR House","checkin":"2013-01-07","checkout":"2013-01-19","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1970","name":"Studio Cottage","checkin":"2013-01-12","checkout":"2013-01-19","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1942","name":"Suite","checkin":"2013-01-15","checkout":"2013-01-20","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""}]
To illustrate the HTML result I need, here is how I currently do it without JSON (strictly in PHP):
<div class="'.$dashboard_list_line_class.'">
<div class="dashboard_list_unitname"> '.$unit_name.'</div>
<div class="dashboard_list_cleaner_datetime"> '.$inclean_datetime.'</div>
<div class="dashboard_list_cleaner_checkin"> '.$checkin.'</div>
<div class="dashboard_list_cleaner_checkout"> '.$checkout.'</div>
<div class="dashboard_list_cleaner_inclean_cleaner"> '.$inclean_cleaner.'</div>
<div class="dashboard_list_cleaner_notes"> '.$inclean_notes.'</div>
</div>
What would the code look like in jQuery or JavaScript to grab the JSON, iterate though the arrays and create the same result as the PHP I have shown? I've been trying for hours, and get different results of puling data - but I just can't make it work.
Thanks for your help!
Here is you complete solution:
$.ajax( "example.php" ).done(function (response) {
//var data = [{"id":"1732","name":"1BR House","checkin":"2012-12-20","checkout":"2012-12-23","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1587","name":"1BR House","checkin":"2012-12-23","checkout":"2013-01-01","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1661","name":"2BR Studio","checkin":"2012-12-25","checkout":"2013-01-02","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1829","name":"Studio Cottage","checkin":"2012-12-25","checkout":"2012-12-29","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1787","name":"Studio Cottage","checkin":"2012-12-29","checkout":"2013-01-08","inclean_cleaner":"","inclean_datetime":"2012-12-29 00:00:00","inclean_notes":""},{"id":"1843","name":"1BR House","checkin":"2013-01-07","checkout":"2013-01-19","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1970","name":"Studio Cottage","checkin":"2013-01-12","checkout":"2013-01-19","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""},{"id":"1942","name":"Suite","checkin":"2013-01-15","checkout":"2013-01-20","inclean_cleaner":"","inclean_datetime":"0000-00-00 00:00:00","inclean_notes":""}];
var data = $.parseJSON(response);
var dashboard_list_unitname = 'change_this';
var booking_id = 'also_change_this';
$(data).each(function (i, row) {
$(row).each(function (j, col) {
var html = '<div class="row_' + i + '">' +
'<div class="' + dashboard_list_unitname + '"> ' + col.name + '</div>' +
'<div class="dashboard_list_cleaner_datetime"> ' + col.inclean_datetime + '</div>' +
'<div class="dashboard_list_cleaner_checkin"> ' + col.checkin + '</div>' +
'<div class="dashboard_list_cleaner_checkout"> ' + col.checkout + '</div>' +
'<div class="dashboard_list_cleaner_inclean_cleaner"> ' + col.inclean_cleaner + '</div>' +
'<div class="dashboard_list_cleaner_notes"> ' + col.inclean_notes + '</div>' +
'</div>';
$('body').append($(html));
});
});
});
jQuery templates can help here.
http://api.jquery.com/jquery.tmpl/ shows several examples of a template being populated from a JSON-like data bundle, and the {{each}} element allows you to iterate over lists to populate rows and cells.
Template:
<li>
Title: ${Name}.
{{each Languages}}
${$index + 1}: <em>${$value}. </em>
{{/each}}
</li>
Data:
var movies = [
{ Name: "Meet Joe Black", Languages: ["French"] },
{ Name: "The Mighty", Languages: [] },
{ Name: "City Hunter", Languages: ["Mandarin", "Cantonese"] }
];
Everyone seems to be assuming knowledge of AJAX calls. It's not complicated, here is an example,
$.get('json/url', function(json_data) {
// do stuff with your data
// like, other people suggested json_data.each(function(item) {
// do stuff
// });
});
You can learn more about it straight from the jQuery docs,
http://api.jquery.com/jQuery.get/
If you need to make a post request just consult the jQuery docs for post, or for the more general article, the jQuery docs for AJAX calls: http://api.jquery.com/jQuery.ajax/.
var table = '';
$.each(json_data, function(index, obj) {
table += '<div>';
for(var x in obj) {
table += '<div class="dashboard_list_unitname"> '+ obj[x]+'</div>';
}
table += '</div>';
});

Categories

Resources