I am trying to populate table data dynamically in JavaScript. I managed to populate it but there is some problem with the styling, here is what I have achieved so far:
And my code to achieve the above:
function populateOverallOverview(result){
var tableData = new Array();
var table = document.getElementById("firstTabOverall");
for(var i = 0; i < result.length; i++){
tableData[i] = new Array('Category: ' + result[i].category + '\n Best selling month: ' + result[i].topMonthStr + '\n Amount: ' + result[i].topAmount.toFixed(2));
}
for(var i = 0; i < tableData.length; i++){
var newRow = table.insertRow(table.length);
for(var j = 0; j < tableData[i].length; j++){
var cell = newRow.insertCell(j);
cell.innerHTML = tableData[i][j];
}
}
}
My HTML code:
<div class="col-md-6">
<table id="firstTabOverall" class="table table-striped" style="font-size:13px">
</table>
</div>
What I wanted to achieve is for each row, there will be 3 different sub-rows for category, best selling month and amount. I am trying to split them into the next line using '\n' but it does not work.
Also, is there any way to bold the category, best selling month and amount wording in this case?
You do quite some unnecessary shifting-around of data. From results into a temp array, from the temp array into the table... why not from results straight into the table? Also, of course \n does not work. Line breaks mean nothing in HTML. You must add each cell individually.
The following looks a lot more straight-forward – and the Array#forEach() method rids you of the need for a separate loop counter, too:
function populateOverallOverview(result){
var table = document.getElementById("firstTabOverall");
// helper function
function addCell(tr, text) {
var td = tr.insertCell();
td.textContent = text;
return td;
}
// insert data
result.forEach(function (item) {
var row = table.insertRow();
addCell(row, 'Category: ' + item.category);
addCell(row, 'Best selling month: ' + item.topMonthStr);
addCell(row, 'Amount: ' + item.topAmount.toFixed(2));
});
}
Instead of repeating the category names in front of the values, write them into the header row. That's how a table is supposed to work anyway, right?
So, maybe this is better:
function populateOverallOverview(result){
var table = document.getElementById("firstTabOverall");
// helper function
function addCell(tr, text) {
var td = tr.insertCell();
td.textContent = text;
return td;
}
// create header
var thead = table.createTHead();
var headerRow = th.insertRow();
addCell(headerRow, 'Category');
addCell(headerRow, 'Best selling month');
addCell(headerRow, 'Amount');
// insert data
result.forEach(function (item) {
var row = table.insertRow();
addCell(row, item.category);
addCell(row, item.topMonthStr);
addCell(row, item.topAmount.toFixed(2));
});
}
Use CSS to style your table and table header. It might be easier to just write the header row into the static HTML source up-front.
If you positively must add bold text inline labels, you could use these document.createElement("b"), to get a <b> element, set its .textContent and then use .appendChild() of the respective container, in this case of the table cell.
You can add plain text the same way - just use document.createTextNode('...your text...') instead and append that.
Related
I want to add <th> headers to a <table> that does not have an "id" but which is in a <div> having a known "id" so I traverse the DOM to find it:
// search <table>
var c = document.getElementById("tablediv").children;
var i; for(i = 0; i < c.length; i++)
{ Output("- " + c[i].nodeName + "<br>"); // show progress
if(c[i].nodeName == "TABLE") break; }
var tablex = c[i]; // that's the right object
var columns = tablex[0].length; // "TypeError: tablex[0] is undefined"
var row = tablex.insertRow(-1);
for(var i = 0; i < columns; i++)
{ var headerCell = document.createElement("TH");
headerCell.innerHTML = tablex[1][i];
row.appendChild(headerCell);
}
And when tablex[0].length; is run it raises "TypeError: tablex[0] is undefined".
I guess var tablex is an incorrect way to assign c[i];.
Can you please let me know how to do it right?
NOTE: the first TD row of the table contains the column titles so either we convert this row to TH or we fetch titles and delete the TD row after a TH row was inserted.
First of all, you don't need to traverse like that. It's easier to query the table directly with querySelector('#tablediv table'). Notice the use of querySelector instead of querySelectorAll, this returns first table inside the node with requested ID.
So the final code would look like this:
var table = document.querySelector('#tablediv table');
// Here you can add check if the table was found (not null) - I'll leave that to you
var firstRow = table.querySelector('tr');
var columns = firstRow.querySelectorAll('td'); // Or th if you have a header cells
console.log(`Number of columns: ${columns.length}`);
var headerRow = document.createElement('tr');
firstRow.parentNode.insertBefore(headerRow, firstRow);
for(var i = 0; i < columns.length; i++) {
var headerCell = document.createElement("TH");
headerCell.innerHTML = columns[i].innerHTML;
headerRow.appendChild(headerCell);
}
firstRow.remove();
Considering the fact that tablex would optimally be a HTMLTableElement, tablex[0] is not defined.
function table() {
var body = document.body,
tbl = document.createElement('table'),
tableId = document.createAttribute('id');
tableId.value = "table";
tbl.setAttributeNode(tableId);
tbl.className = 'table2';
var id = 0;
for (var i = 0; i < 30; i++) {
var tr = tbl.insertRow();
tr.setAttribute("data-id", i, 0);
for (var j = 0; j < 4; j++) {
var td = tr.insertCell();
td.appendChild(document.createTextNode(""));
td.id = "td" + id ;
id++;
}
}
$(".middletablediv").append(tbl);
};
table();
i have dynamic table which contain td and th i add div for table td but it also effect the th .i don't want that div in th i want div only in div
$('tr:first-child').children('td').replaceWith(function(i, html) {
return '<th>' + html + '</th>';
});
this code is used for change first row td into th
and
$('#table td').wrapInner('<div class="tddivcolor divtime" />');
this for adding class to td
The only reason I could see is the order of your script execution.
If you are running the wrapping code first then the td->td conversion code then the divs will get added to the first row also.
So one solution is to fix the order and move the th conversion code first.
If that is not possible then you can exclude the first row from wrapping
$('#table tr:not(:first-child) td').wrapInner('<div class="tddivcolor divtime" />');
If you know the specific, try to use append if it works for you.
<table><tr><td>...
this not be the exact answer you need, but might lead to proper direction.
like where you want to put div, then try this, i used this to my selector class to create 'div'
$("#SelectorID").append("<div class= EmpList id=" + empID + ">" + selectedList[empID] + " <span class='close'>×</Span> </div>");
I tried to make the page add rows and five cells to each table, however I'm having some problems. I appended the row first to the table then followed by looping through the and adding five cells to each row, however whenever I ran it in my web browser it produced this:
I want the cells to be a child of the table row.
function addRows(ramnt) {
if(ramnt > 0){
var cellcount = 5;
var tccount = 0;
table.append('<tr>');
console.log('Appended <tr>');
while(tccount < cellcount){
tccount = tccount + 1;
table.append('<td id="Cell-' + tccount + '" class="gencell"></td>');
}
if (tccount = cellcount){
table.append('</tr>');
ramnt = ramnt - 1;
addRows(ramnt);
}
}
}
console.log('Working');
var table = $('Table');
addRows(5);
I would advise making your function a little more dynamic. Here is what I would suggest:
function addRows(rc, to) {
if(rc > 0){
var cellcount = 5;
for(var i = 0; i < rc; i++){
var row = $("<tr>", { id: "Row-" + i });
for(var c = 0; c < cellcount; c++){
row.append("<td id='Cell-" + c + "' class='gencell'></td>");
}
to.append(row);
console.log("Row " + i + " created");
}
return true;
} else {
return false;
}
}
Then you can pass the Number of Rows and the Table Object like so:
addRows(5, $("table"));
As I said, I would advise setting your table like so:
<table id="myTable"></table>
This way if you later add another table or do something differnt, you can still use the same code:
addRows(5, $("#myTable"));
Working Example: https://jsfiddle.net/Twisty/Lysr2n5v/
You can take a bit further to write to function to accept X number of Rows, N number of Cells per Row, and the table Object: https://jsfiddle.net/Twisty/Lysr2n5v/2/
function addRows(rc, cc, to) {
if(rc > 0){
for(var i = 0; i < rc; i++){
var row = $("<tr>", { id: "Row-" + i });
for(var c = 0; c < cc; c++){
row.append("<td id='Cell-" + c + "' class='gencell'></td>");
}
to.append(row);
console.log("Row " + i + " created");
}
return true;
} else {
return false;
}
}
When you call table.append('<tr>'), jQuery inserts both opening and closing tags. I tried this:
Then you call table.append('<td id="Cell-' + tccount + '" class="gencell"></td>');, which appends the td element at the end of the table, so it goes after the tr you appended before.
What you need to do is insert the tr as you did, but then select this tr and append into it. So something like this:
table.find('tr:last').append('<td id="Cell-' + tccount + '" class="gencell"></td>');
You need to create a row, append all the columns to that row, then append the row to the table like below.
I would also recommend adding logic to check the number of columns already present in the table and make sure you dont add more than are there now as that would not be valid.
With the below:
addRows(5,5) - will add 5 rows to every table on the page where each row will the same number of columns as the table currently has or 5 columns if the table doesnt currently have any columns
addRows(5,5,'#myTable') - will add 5 rows to the table with the id myTable where each row will the same number of columns as the table currently has or 5 columns if the table doesnt currently have any columns
function addRows(rowCount, colCount, table) {
var $tables= table ? $(table) : $('table');
$tables.each(function(){
console.log('table');
$this=$(this);
colCount =$this.find('tr:eq(0)').find('td').length || colCount // limit the number of added cols to the numer already present
for(r=0;r<rowCount;r++){
var $row=$('<tr>');
for(c=0;c<colCount;c++){
$row.append('<td>');
}
$this.append($row);
}
});
}
addRows(5,5);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1"></table>
<br>
<br>
<br>
<br>
<br>
<table border="1"><tr>
<td>some content</td>
<td>some content</td>
<td>some content</td>
</tr></table>
I need to add a nested table to each row of a jquery datatable(using legacy datatables). So, I tried using example from datatables.net for child rows and modifying it to my needs as I need for the child rows to show at all times, rather than on clicking the parent row.Here is the code I am using both to build my inner table and then display it..
function buildInnerTable(){
var keys = Object.keys(reportApp.gridData),
len = keys.length,
j = 0,
prop,
value;
while (j < len) {
prop = keys[j];
value = reportApp.gridData[prop];
detLen = value.detail.length;
var rowVals = [];
for(var i = 0; i < detLen; i++){
tmpRow = "<tr><td>"+value.detail[i].invtid+"</td>"+
"<td>"+value.detail[i].bf+"</td>"+
"<td>"+value.detail[i].qtyship+"</td>"+
"<td>"+value.detail[i].ordqty+"</td>"+
"<td>"+value.detail[i].bf+"</td>"+
"<td>"+value.detail[i].exttreating+"</td>"+
"<td>"+value.detail[i].extpriceinvc+"</td>"+
"<td>"+value.detail[i].misc+"</td>"+
"<td>"+value.detail[i].extother+"</td>"+
"<td>"+value.detail[i].calcext+"</td></tr>";
rowVals.push(tmpRow);
}
setTableRow(rowVals , j);
j += 1;
}
function setTableRow(rowVals , ndx){
$("#gridTbl > tbody > tr:eq("+ ndx+ ")").after("<table><tr><th>InvtID</th>"+
"<th>Clss</th><th>Pieces</th><th>BilQty</th><th>BF</th><th>Treating</th>"+
"<th>Wood</th><th>NEED NAME</th><th>Other</th><th>Misc</th><th>Total</th></tr>"+
rowVals);
But, I am not getting what I need to get. What it looks like is that the datatables adds a new row and then sets the new table inside the first cell on new row. However, when I view source, that isn't what is happening at all. It closes the previous row and then inserts new table...
I am attaching a screenshot. What I need is for the details to show below the main item rows and to be aligned in same way. Any help in where I am wrong will be greatly appreciated.
Ok... Finally figured this out.
In order to make the view show normally, I had to add a new row to the datatable and then, in side that row, add my new table. However, this caused an indexing issue with the table. So, I had to check the index each time before I added new row. I am posting working code in the hope that it will help someone else.
function buildInnerTable(){
var keys = Object.keys(reportApp.gridData),
len = keys.length,
j = 0,
prop,
value;
while (j < len) {
prop = keys[j];
value = reportApp.gridData[prop];
detLen = value.detail.length;
var rowVals = [];
//THIS NEXT LINE IS WHERE I GET MY INDEX...
var ndx = ($("tr:contains("+value.invcnbr+ ")").index());
for(var i = 0; i < detLen; i++){
tmpRow = "<tr><td>"+value.detail[i].invtid+"</td>"+
"<td>"+value.detail[i].bf+"</td>"+
"<td>"+value.detail[i].qtyship+"</td>"+
"<td>"+value.detail[i].ordqty+"</td>"+
"<td>"+value.detail[i].bf+"</td>"+
"<td>"+value.detail[i].exttreating+"</td>"+
"<td>"+value.detail[i].extpriceinvc+"</td>"+
"<td>"+value.detail[i].misc+"</td>"+
"<td>"+value.detail[i].extother+"</td>"+
"<td>"+value.detail[i].calcext+"</td></tr>";
rowVals.push(tmpRow);
}
setTableRow(rowVals,ndx);
}
j += 1;
}
}
function setTableRow(rowVals,ndx){
var outerTbl = $('#gridTbl').DataTable();
var tr = $("#gridTbl > tbody > tr:eq("+ ndx+ ")");
//NOTE HOW I ADD A ROW AND THEN ADD NEW TABLE TO CELL IN THE ROW.
var innerTbl = "<tr><td colspan = 10><table style = 'background- color:#FFFFFF; width:100%; border:1px solid;'><tr><td>InvtID</td>"+
"<td>Clss</td><td>Pieces</td><td>BilQty</td><td>BF</td><td>Treating</td>"+
"<td>Wood</td><td>NEED NAME</td><td>Other</td><td>Misc</td><td>Total</td></tr>"+
rowVals + "</td></tr>";
tr.after(innerTbl).show();
}
I want to get all classes of the HTML element on my page, split it and store it in array. After that I want to write it into my table in the div with the id "table" which I already have.
So far I have this code:
var string = $('html').attr('class');
var array = string.split(' ');
var arrayLength = parseInt(array.length);
for (i=0; i<=arrayLength; i++) {
// code
}
<div id="test><!-- table goes here --></div>
Can you help me with the rest?
btw, the HTML element has the classes from a modernizr.js.
PS: The code is combination of pure JS and jQuery. Because I dont know how to get all classes of the HTML element in pure JS. Any Idea?
If you're trying to remove jQuery altogether use this:
// Get array of classes without jQuery
var array = document.getElementsByTagName('html')[0].className.split(/\s+/);
var arrayLength = array.length;
var theTable = document.createElement('table');
// Note, don't forget the var keyword!
for (var i = 0, tr, td; i < arrayLength; i++) {
tr = document.createElement('tr');
td = document.createElement('td');
td.appendChild(document.createTextNode(array[i]));
tr.appendChild(td);
theTable.appendChild(tr);
}
document.getElementById('table').appendChild(theTable);
if you have a table already in the html
<div id="test><table >
</table>
</div>
you can simply append new rows to it,
var string = $('html').attr('class');
var array = string.split(' ');
var arrayLength = parseInt(array.length);
for (i=0; i<=arrayLength; i++) {
$("#test table") .append('<tr><td>'+array[i]+'</td></tr>')
}
It is not clear if you want the class names per row or per column. These examples are one class name per row. Try this:
var elm = $('#test'),
table = $('<table>').appendTo(elm);
$(document.documentElement.className.split(' ').each(function() {
table.append('<tr><td>'+this+'</td></tr>');
});
I used native code to get the classNames of the HTML element: document.documentElement.className, but you might as well use $('html').attr('class').
A native JS example using innerHTML:
var d = window.document,
elm = d.getElementById('test'),
html = '<table>',
classes = d.documentElement.classNames.split(' '),
i = 0;
for(; classes[i]; i++) {
html += '<tr><td>' + classes[i] + '</td></tr>';
}
elm.innerHTML = html + '</table>;