Is there a way to build dynamically a table-like structure from a data-set on websites (in javascript)?
In pseudo-code something like:
function pseudo(dataset) {
<table>
<th>dataset.name, dataset.id</th>
foreach dataset.schedular.array as a {
<tr><td>a.start_time</td><td>a.end_time</td><td>a.client.name</td></tr>
}
</table>
}
and executed like:
<div>
<script>pseudo(json[employee[0]]);</script>
</div>
In php i used smarty-templates to "fill" data into similar masks, now i need something similar in javascript.
Are jquery widgets or plugins that what i m looking for? And where can i find helpful tutorials or books?
your html page:
<div id="dataToDisplay"></div>
your java script function:
function pseudo(dataset) {
var tableContents = "<table>";
tableContents = tableContents+ "<th>"+dataset.name, dataset.id+"</th>";
foreach dataset.schedular.array as a {
tableContents =tableContents + "<tr><td>"+a.start_time+"</td><td>"+a.end_time+"</td><td>"+a.client.name+"</td></tr>";
}
tableContents = tableContents + "</table>";
document.getElementById("dataToDisplay").innerHTML = tableContents;
}
I use jQuery and the following construct. employees is an JS array of objects. The HTML table is prepared like this:
<table id="clients">
<thead><tr><th>Start</th><th>End</th><th>Name</th></tr></thead>
<tbody></tbody>
</table>
Then the following jQuery-loop using each is used to append the lines:
$.each(employees, function(index, employee){
$('#clients > tbody').append(listItem(index, employee));
});
where listItem() is a function that returns the table line. Of course, this could be done more elegantly:
function listItem(index, employee) {
var item = '<tr>';
item += '<td>' + employee.start_time + '</td>';
item += '<td>' + employee.end_time + '</td>';
item += '<td>' + employee.name + '</td>';
item += '</tr>';
return item;
}
Take a look at "jqGrid"
http://www.trirand.com/blog/
it's a plugin which takes JSON and biulds tables from it. However it uses jQuery.
Related
I'm getting JSon data from my server and building a table with this data. The last column of the table is a button that will grab the fields from the selected row to populate another fields, but it is returning: ReferenceError: response.DATA is not defined.
response = JSON.parse(response);
$('.myDiv').empty();
// Header
var table = '<table class="table table-striped"><thead><tr><th>First Name</th><th>Last Name</th><th>City</th><th>State</th><th>ZIP</th><th>Action</th></tr></thead><tbody>';
var i;
for(i=0; i<response.ROWCOUNT; i++){
table += '<tr>';
table += '<td>' + response.DATA.PROVIDERFIRSTNAME[i] + '</td>';
table += '<td>' + response.DATA.PROVIDERLASTNAME[i] + '</td>';
table += '<td>' + response.DATA.PROVIDERCITY[i] + '</td>';
table += '<td>' + response.DATA.PROVIDERSTATE[i] + '</td>';
table += '<td>' + response.DATA.PROVIDERPOSTALCODE[i] + '</td>';
table += '<td><input type="button" class="btn btn-primary" value="select" onClick="setData(response.DATA, i);" /></td>';
table += '</tr>';
}
table += '</tbody></table>';
$('.myDiv').append(table);
My setData function:
function setData(data, pos){
console.debug(data.PROVIDERFIRTNAME[pos]);
}
You're using an inline handler, and an inline handler can only reference global variables. Attach the listener properly using Javascript instead, so that it can reference the variables (most importantly, response and i) properly. Also make sure i is block scoped with let, rather than function-scoped.
You can also consider using template literals to make the code a lot more readable:
// Header
const $table = $('<table class="table table-striped"><thead><tr><th>First Name</th><th>Last Name</th><th>City</th><th>State</th><th>ZIP</th><th>Action</th></tr></thead><tbody></tbody>');
// make sure to use "let i" here
for (let i = 0; i < response.ROWCOUNT; i++) {
const $row = $(`
<tr>
<td>${response.DATA.PROVIDERFIRSTNAME[i]}</td>
<td>${response.DATA.PROVIDERLASTNAME[i]}</td>
<td>${response.DATA.PROVIDERCITY[i]}</td>
<td>${response.DATA.PROVIDERSTATE[i]}</td>
<td>${response.DATA.PROVIDERPOSTALCODE[i]}</td>
<td>${response.DATA.PROVIDERPOSTALCODE[i]}</td>
<td><input type="button" class="btn btn-primary" value="select"/></td>
</tr>
`);
$row.find('input').on('click', () => {
console.debug(response.DATA.PROVIDERFIRSTNAME[i]);
});
$table.find('tbody').append($row);
}
$('.myDiv').append(table);
Spelling matters - make sure to use PROVIDERFIRSTNAME instead of PROVIDERFIRTNAME.
Inline handlers are pretty universally considered to be poor practice - best to avoid them whenever possible.
I have this jQuery function were I create a table:
function propertyView(values) {
// build the table
var frame = '<fieldset id = "propertiesValueArea" style="border: solid 1px #6b6b6b;">';
var content = frame + smallHeader + '<table data-role="table" id="propertiesList"><thead><tr></tr></thead>';
$.each($(values), function () {
var data1 = this.RealValue.FieldValue;
var data2 = this.RealValue.Id;
//create tables row
content += '<tr data-id=' + this.Id + '>';
content += '<td style="vertical-align: inherit;text-align:center;"><label for="">' + this.FieldName + '</label></td>';
if (this.FieldValue.indexOf(',') > -1) {
content += '<td style="text-align:center;"><select>';
this.FieldValue.split(',').forEach(function (item) {
if (data1 === item) //Here data1 is undefined!!!
{
content += '<option selected="selected" value="">' + item + '</option>';
}
else {
content += '<option value="">' + item + '</option>';
}
})
content += '</select></td>';
}
else {
content += '<td style="text-align:center;"><input type="text" id="propFieldName" data-id="' + this.Id + '" value="' + congiValue(this.FieldValue, this.RealValue) + '"/>';
}
content += '</tr>';
});
content += '</table>';
content += '</fieldset>'
return content;
}
Inside outter each function I create 2 variables:
var data1 = this.RealValue.FieldValue;
var data2 = this.RealValue.Id;
I try to create this variable inside inner each:
if (data1 === item) //Here data1 is undefined!!!
But on this row I get this error:
Uncaught ReferenceError: data1 is not defined
Any idea why data1 is undefined?
It can be undefined only because this.RealValue.FieldValue or this.RealValue is undefined
It looks like
var data1 = this.RealValue.FieldValue; //it's value is undefined
this.FieldValue //it's value is undefined
try to
console.log(this.FieldValue)
console.log(data1)
After that you can easily found where you are getting an error and why. Else everything looks fine with your code.
I have encountered similar problem before. It took me several hours to discover the problem. Now that aside there some things which is not clear here.
is the value coming from another function's operation? If
this.RealValue.FieldValue;
is coming from e.g. a result of maybe another function then you would need to use async/await to ensure that the function completes its operation and there is data in this.RealValue.FieldValue before you move on to the next line of code.
Maybe the this.RealValue.FieldValue itself does not have any thing assigned to it outside of the function itself.
In order to help you we would need a complete code. If you think your code is too private then you can go through it by trying what #Negi Rox said earlier.
Put console.log(this.RealValue.FieldValue) at various strategic locations in your code to determine when it was assigned a value.
this is for a web app that will take in a survey I am using firebase. What I need help in is when the app is exporting the data into a table it grabs the data but won't is able to push it to the table any help would be appreciated. Since the HTML code is a long one I will only put the table portion:
the table portion of the HTML file
<div id = "table">
<pre id = "snap-test"></pre>
<table id ="File-Table" class="table">
<thead>
<tr>
'<td><button onclick = "DeleteTabele()" id = "Delete-btn">Delete File</button></td>'
</tr>
</thead>
<button onclick ="Return()" id= "Log-btn" type="submit" class="btn btn-">Add a new File</button>
</table>
</div>
the Table.js file
var table = document.getElementById("File-Table");
const file = $("#File").val();
var requests = [];
function Export(){
//calls the file id in the HTML element
$("#Survey-Page").hide();
$("#File-Table").show();
$("#Log-btn").show();
var result = [];
//calls the database from the firebase known as users then using a function we nest a snapshot in it for later
firebase.database().ref('/users/').once('value').then(function(snapshot){
//if snapshot is empty then the window will alert
if (snapshot.val() == null){
alert("Does not exist");
}
// if the snapshot is full then it will genereate a table based on the snapshot value of the database
else {
console.log(snapshot.val());
let result = snapshot.val()
for(let k in result){
this.requests.push({
id: k,
value: result[k]
});
}
var MyTable = '<tr>' +
'<td>' + snapshot.val().txtName +'</td>' +
'<td>' + snapshot.val().txtEmail +'</td>' +
'<td>' + snapshot.val().FileName + '</th>' +
'<td><button id = "Email-btn">Send Survey</button></td>' +
'<td><button onclick = "DeleteTabele()" id = "Delete-btn">Delete File</button></td>' +
'</tr>';
MyTable += "</tr></table>";
table.innerHTML = MyTable;
}
console.log(snapshot.val());
});
From the code you have published, the more probable cause is that your reference is referencing a node of multiple users and not a specific user.
firebase.database().ref('/users/')
To confirm this assumption we need to see your database structure. Can you edit you post?
However, let's imagine this assumption is correct. Then you have two solutions:
If you want to display the value of ONE user which is under the users node, you have to change the reference and point to this user, e.g.:
firebase.database().ref('/users/' + userID)
Then the rest of the code will work normally
If you want to display in your table the entire list of users (one by row) you have to loop over the results of the query, as follow:
firebase.database().ref('/so').once('value').then(function(snapshot){
var MyTable;
snapshot.forEach(function(childSnapshot) {
MyTable += '<tr>' +
'<td>' + childSnapshot.val().txtName +'</td>' +
'<td>' + childSnapshot.val().txtEmail +'</td>' +
// ...
'<td><button id = "Email-btn">Send Survey</button></td>' +
'<td><button onclick = "DeleteTabele()" id = "Delete-btn">Delete File</button></td>' +
'</tr>';
});
table.innerHTML = MyTable;
});
See the doc here: https://firebase.google.com/docs/database/web/lists-of-data#listen_for_value_events
In addition, if I may, you could have a look at this SO post: HTML : draw table using innerHTML which shows some best practices for writing rows of a table in "simple" JavaScript.
I am trying to create a HTML table like the following dynamically using jQuery:
<table id='providersFormElementsTable'>
<tr>
<td>Nickname</td>
<td><input type="text" id="nickname" name="nickname"></td>
</tr>
<tr>
<td>CA Number</td>
<td><input type="text" id="account" name="account"></td>
</tr>
</table>
This is my actual table :
<table border="0" cellpadding="0" width="100%" id='providersFormElementsTable'> </table>
This is the method which will create tr and td elements taking id and labelText:
function createFormElement(id, labelText) {
// create a new textInputBox button using supplied parameters
var textInputBox = $('<input />').attr({
type: "text", id: id, name: id
});
// create a new textInputBox using supplied parameters
var inputTypeLable = $('<label />').append(textInputBox).append(labelText);
// append the new radio button and label
$('#providersFormElementsTable').append(inputTypeLable).append('<br />');
}
I also have a value which will be shown as tool tip.
Please help me to create a table dynamically with tool tip and tr td.
EDIT:
I have almost done with the following code:
function createProviderFormFields(id, labelText,tooltip,regex) {
var tr = '<tr>' ;
// create a new textInputBox
var textInputBox = $('<input />').attr({
type: "text",
id: id, name: id,
title: tooltip
});
// create a new Label Text
tr += '<td>' + labelText + '</td>';
tr += '<td>' + textInputBox + '</td>';
tr +='</tr>';
return tr;
}
Here label is coming properly and the input box is not coming and it shows [object Object] where the text box has to come...
When I printed the textInputBox using console.log, I get the following:
[input#nickname, constructor: function, init: function, selector: "", jquery: "1.7.2", size: function…]
What could be the issue?
Thanks to #theghostofc who showed me path... :)
You may use two options:
createElement
InnerHTML
Create Element is the fastest way (check here.):
$(document.createElement('table'));
InnerHTML is another popular approach:
$("#foo").append("<div>hello world</div>"); // Check similar for table too.
Check a real example on How to create a new table with rows using jQuery and wrap it inside div.
There may be other approaches as well. Please use this as a starting point and not as a copy-paste solution.
Edit:
Check Dynamic creation of table with DOM
Edit 2:
IMHO, you are mixing object and inner HTML. Let's try with a pure inner html approach:
function createProviderFormFields(id, labelText, tooltip, regex) {
var tr = '<tr>' ;
// create a new textInputBox
var textInputBox = '<input type="text" id="' + id + '" name="' + id + '" title="' + tooltip + '" />';
// create a new Label Text
tr += '<td>' + labelText + '</td>';
tr += '<td>' + textInputBox + '</td>';
tr +='</tr>';
return tr;
}
An example with a little less stringified html:
var container = $('#my-container'),
table = $('<table>');
users.forEach(function(user) {
var tr = $('<tr>');
['ID', 'Name', 'Address'].forEach(function(attr) {
tr.append('<td>' + user[attr] + '</td>');
});
table.append(tr);
});
container.append(table);
Here is a full example of what you are looking for:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$( document ).ready(function() {
$("#providersFormElementsTable").html("<tr><td>Nickname</td><td><input type='text' id='nickname' name='nickname'></td></tr><tr><td>CA Number</td><td><input type='text' id='account' name='account'></td></tr>");
});
</script>
</head>
<body>
<table border="0" cellpadding="0" width="100%" id='providersFormElementsTable'> </table>
</body>
I understand you want to create stuff dynamically. That does not mean you have to actually construct DOM elements to do it. You can just make use of html to achieve what you want .
Look at the code below :
HTML:
<table border="0" cellpadding="0" width="100%" id='providersFormElementsTable'></table>
JS :
createFormElement("Nickname","nickname")
function createFormElement(labelText, id) {
$("#providersFormElementsTable").html("<tr><td>Nickname</td><td><input type='text' id='"+id+"' name='nickname'></td><lable id='"+labelText+"'></lable></td></tr>");
$('#providersFormElementsTable').append('<br />');
}
This one does what you want dynamically, it just needs the id and labelText to make it work, which actually must be the only dynamic variables as only they will be changing. Your DOM structure will always remain the same .
WORKING DEMO:
Moreover, when you use the process you mentioned in your post you get only [object Object]. That is because when you call createProviderFormFields , it is a function call and hence it's returning an object for you. You will not be seeing the text box as it needs to be added . For that you need to strip individual content form the object, then construct the html from it.
It's much easier to construct just the html and change the id s of the label and input according to your needs.
FOR EXAMPLE YOU HAVE RECIEVED JASON DATA FROM SERVER.
var obj = JSON.parse(msg);
var tableString ="<table id='tbla'>";
tableString +="<th><td>Name<td>City<td>Birthday</th>";
for (var i=0; i<obj.length; i++){
//alert(obj[i].name);
tableString +=gg_stringformat("<tr><td>{0}<td>{1}<td>{2}</tr>",obj[i].name, obj[i].age, obj[i].birthday);
}
tableString +="</table>";
alert(tableString);
$('#divb').html(tableString);
HERE IS THE CODE FOR gg_stringformat
function gg_stringformat() {
var argcount = arguments.length,
string,
i;
if (!argcount) {
return "";
}
if (argcount === 1) {
return arguments[0];
}
string = arguments[0];
for (i = 1; i < argcount; i++) {
string = string.replace(new RegExp('\\{' + (i - 1) + '}', 'gi'), arguments[i]);
}
return string;
}
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.