jQuery append td to dynamically created tr - javascript

I have a div with a table and I'd like to append a row with multiple td to it:
var $tblBody = $('#' + btn.attr('data-tbody-id')); //tbody of the Table
// Append the Row
$tblBody.append('<tr id="row_'+data.extra.span+'_'+data.extra.id+'_temp">');
var $tblRow = $('<tr id="row_'+data.extra.span+'_'+data.extra.id+'_temp">');
//Loop through my data and append tds
$.each(data.extra.fields, function (i, v) {
console.log(i); //Shows 0,1,2,3 etc.
$tblRow.append('' +
'<td class="' + v.cellClass + '">' +
' <span class="'+data.extra.span+'_'+v.name+'_'+data.extra.id+'">' + v.value + '</span>' +
'</td>'
)
});
Unfortunately the created to stays empty:
<tr id="row_ZWxoQXArUi82K3BjaFY4Y0x2ZWR3UT09_41_temp"></tr>
I found this: https://stackoverflow.com/a/42040692/1092632 but why is the above not working for me?

First make the tds of the row, after that append whole tr to the body.
Remove this line
$tblBody.append('<tr id="row_'+data.extra.span+'_'+data.extra.id+'_temp">');,
because you don't have a reference on it and use append part of your code after the loop.
var $tblRow = $('<tr id="row_'+data.extra.span+'_'+data.extra.id+'_temp">');
$.each(data.extra.fields, function (i, v) {
console.log(i); //Shows 0,1,2,3 etc.
$tblRow.append('' +
'<td class="' + v.cellClass + '">' +
' <span class="'+data.extra.span+'_'+v.name+'_'+data.extra.id+'">' + v.value + '</span>' +
'</td>'
)
});
$tblBody.append($tblRow); // <-----------------------

This line
var $tblRow = $('<tr id="row_'+data.extra.span+'_'+data.extra.id+'_temp">');
creates a new reference which is not in DOM yet.
instead, replace it with this
var $tblRow = $tblBody.find( "#row_' + data.extra.span + '_' + data.extra.id + '_temp">');
This will now get you the handle to the same row which has already been appended to the DOM.

Here you with one more solution using ES6 template literals
var $tblBody = $('#' + btn.attr('data-tbody-id')); //tbody of the Table
// Append the Row
var rowid = 'row_' + data.extra.span + '_' + data.extra.id + '_temp';
$tblBody.append(`<tr id=${rowid} />`);
//Loop through my data and append tds
$.each(data.extra.fields, function (i, v) {
console.log(i); //Shows 0,1,2,3 etc.
$(`#${rowid}`).append(
`<td class="${v.cellClass}">
<span class="${data.extra.span}_${v.name}_${data.extra.id}">
${v.value}
</span>
</td>`);
});
Once you appended the tr then use the id instead of get the row & appending the td.
Hope this will help you.

change the code to something like this
var $tblBody = $('#' + btn.attr('data-tbody-id')); //tbody of the Table
// Append the Row
$tblBody.append('<tr id="row_'+data.extra.span+'_'+data.extra.id+'_temp"></tr>');
var $tblRow = $('#'+'row_'+data.extra.span+'_'+data.extra.id+'_temp');
//Loop through my data and append tds
$.each(data.extra.fields, function (i, v) {
console.log(i); //Shows 0,1,2,3 etc.
$tblRow.append('' +
'<td class="' + v.cellClass + '">' +
' <span class="'+data.extra.span+'_'+v.name+'_'+data.extra.id+'">' + v.value + '</span>' +
'</td>'
)
});

You forgot to append tblRow to the tblBody. Adding the last line would fix your code
// Append the Row
$tblBody.append('<tr
id="row_'+data.extra.span+'_'+data.extra.id+'_temp">');
var $tblRow = $('<tr
id="row_'+data.extra.span+'_'+data.extra.id+'_temp">');
//Loop through my data and append tds
$.each(data.extra.fields, function (i, v) {
console.log(i); //Shows 0,1,2,3 etc.
$tblRow.append('' +
'<td class="' + v.cellClass + '">' +
' <span
class="'+data.extra.span+'_'+v.name+'_'+data.extra.id+'">' + v.value +
'</span>' +
'</td>'
)
});
$tblBody.append($tblRow);

Related

Coffeescript : For loop to concatenate HTML <td> element

Playing around a coffeescript. I have the following for loop to concat a html element in native javascript which works well. At the moment I just couldnt get the value json data i.e i.a , i.b from coffeescript.
//.js file
function createTr(json){
var tr='';
for (var i=0;i<json.data.length;i++){
var data ='<tr><td>' + json.data[i].a + ' - ' + json.data[i].b +
'</td>'+
'<td>' + json.data[i].c +
'</td>'+
'<td>' + json.data[i].d +
'</td>'+
'</tr>';
tr +=data;
}
return tr;
}
The coffescript is per below
//.coffeescript
createTr = (json) ->
tr=''
tr + '<tr><td>' + i.a + '-' + i.b+'</td> <td>'+i.c+'</td><td>'+i.d+'</td></tr>' for i in json.data
tr
the source map for the autogenerated javascript from the coffeescript as per below
//autogenerated js file from coffeescript file above
createTr = function(json) {
var i, j, len, ref, tr;
tr = '';
ref = json.data;
for (j = 0, len = ref.length; j < len; j++) {
i = ref[j];
tr + '<tr><td>' + i.a + '-' + i.b + '</td><td>' + i.c + '</td><td>' + i.d + '</td></tr>';
}
return tr;
};
The only difference is a missing assignment. The CoffeeScript version should be:
createTr = (json) ->
tr=''
tr += '<tr><td>' + i.a + '-' + i.b+'</td> <td>'+i.c+'</td><td>'+i.d+'</td></tr>' for i in json.data
tr
##.coffee file
createTr = (json) ->
tr = ''
for item in json.data
data = """<tr>
<td>#{item.a}-#{item.b}</td>
<td>#{item.c}</td>
<td>#{item.d}</td></tr> """
tr += data
return tr
And read http://coffeescript.org/ about loop, string and variables in string like "Some text #{variable}"
I prefer to use a join on the array that the for loop creates:
createTr = (json) ->
('<tr><td>' + i.a + '-' + i.b+'</td> <td>'+i.c+'</td><td>'+i.d+'</td></tr>' for i in json.data).join("")
or kind of like #yavor.makc if it was my code I might focus on readability:
createTr = (json) ->
(for i in json.data
"
<tr>
<td>#{i.a}-#{i.b}</td>
<td>#{i.c}</td>
<td>#{i.d}</td>
</tr>
"
).join("")

How to optimize the DOM inserting loop

For example : I want to insert many tr in a table like this
var tbody = $('#tbody')
// Suppose the articlelist is the data from ajax
while (articlelist.length > 0) {
var article = articlelist.shift(),
var tr = $(' <tr>'
+' <td>'+article.id+'</td>'
+'<td>' + article.channelid +'</td>'
+ '<td>'+article.comment+'</td>'
+'<td>'+article.last_edit_time+'</td><td>'
)
tbody.append(tr)
}
To avoid create the <tr>...</tr> in loop .Is it possible to use a class to generate the tr content ?
An optimized version:
var tbody = $('#tbody'),
htmlStr = "";
for (var i = 0, len = articlelist.length; i < len; i++) { // avoid accessing 'length' property on each iteration
htmlStr += '<tr><td>' + articlelist[i].id + '</td>'
+ '<td>' + articlelist[i].channelid + '</td>'
+ '<td>' + articlelist[i].comment + '</td>'
+ '<td>' + articlelist[i].last_edit_time + '</td><td><tr>';
}
tbody.append(htmlStr); // parses the specified text as HTML or XML and inserts the resulting nodes
You could use a loop to concatenate all the strings, then append this lengthy string all at once. This would help with performance for many trs
var tbody = $('#tbody')
var rows = ''
while (articlelist.length > 0) {
var article = articlelist.shift(),
rows += '<tr><td>'+article.id+'</td>'
+'<td>' + article.channelid +'</td>'
+ '<td>'+article.comment+'</td>'
+'<td>'+article.last_edit_time+'</td><tr>';
}
tbody.append(rows)
add a function like this to do this for you.
while (articlelist.length > 0) {
make_content(article);
}
function make_content(article) {
var tbody = $('#tbody');
var tr = $(' <tr>'
+' <td>'+article.id+'</td>'
+'<td>' + article.channelid +'</td>'
+ '<td>'+article.comment+'</td>'
+'<td>'+article.last_edit_time+'</td><td>'
)
tbody.append(tr)
}

Table row click listener stopped working

I am adding rows to a table dynamically using the following function. Upon a row click the table disappears and another div is generated and populated dynamically. It was all working perfectly till 2 hours ago, when suddenly without me changing any code it stopped. I am not sure if the following code is sufficient enough for someone to give me an answer but does anyone see any particular reason this will stop working all of the sudden ?
var setupProjectListTable = function (ipProject, table, tableContainer) {
$('#' + table + ' tr').hover(function() {
$(this).addClass('hover');
}, function() {
$(this).removeClass('hover');
});
var title = ipProject.getTitle();
var desc = ipProject.getDesc();
var applicableDegrees = ipProject.getApplicableDegreeList();
var keywordList = ipProject.getKeywordList();
$('#' + table + ' tbody').append(
'<tr id = "' + title + '">' +
'<td>' + title + '</td>' +
'<td>' + desc + '</td>' +
'<td>' + applicableDegrees + '</td>' +
'<td>' + keywordList + '</td></tr>'
);
$("#" + title).click( function(e) {
e.preventDefault();
$('#' + tableContainer).hide();
generateProjectDetails(ipProject);
});
};
It's simple. click() Only affects existing elements but not added elements.
so use on():
$("tbody").on('click', '#' + title, function(e) {
e.preventDefault();
$('#' + tableContainer).hide();
generateProjectDetails(ipProject);
});

Looping through my table, how do I know if the checkbox is checked?

How I build my table:
for (var i = 0; i < result.length; i++) {
var item = result[i];
// Firma, BygningselementNavn, BrugerNavn, EmailAdresse, Telefon
tbody = tbody + '<tr class="modtagerRow"><td>' + item.FirmaNavn + '</td>' +
'<td>' + item.BygningselementNavn + '</td>' +
'<td>' + item.BrugerNavn + '</td>' +
'<td>' + item.EmailAdresse + '</td>' +
'<td>' + item.Telefon + '</td>'
// Medtag
tbody = tbody + '<td style="text-align:center"><input type="checkbox"
value="' + item.BygningselementId + '_' + item.BrugerId + '"
name="BygningsElementBrugerComboIds"></td>' + '</tr>';
}
$('#ModtagereTable tbody').append(tbody)
How I am trying to loop through the rows and adding a CSS class to rows that has it's checkbox checked.
1) I get the indexies to the console, but I can't make the if condition for all the checked checkboxes.
2) Also I am not sure if I can you $( this ) or I should use something else, when adding the class .hideForSendMailConfirm?
// Looping rows in table
$( ".modtagerRow" ).each(function(index, element) {
console.log('index: ' + index);
// if
if (element.checked) {
$( this ).addClass(".hideForSendMailConfirm");
}
});
Try this
$('.modtagerRow input:checked').closest('tr').addClass('hideForSendMailConfirm');
to add class to the rows that are not checked. You can use .not()
$('.modtagerRow input[type="checkbox"]').not(':checked').closest('tr').addClass('hideForSendMailConfirm');
Your code:
$(".modtagerRow").each(function (index, element) {
if (element.checked) {
$(this).addClass(".hideForSendMailConfirm");
}
});
is actually looping through the table row having class modtagerRow and a table row does not have any checked property and hence your code is not working.
You can do something like this:
$(".modtagerRow :checkbox").each(function (index, element) {
if (element.checked) {
$(this).closest(".modtagerRow").addClass("hideForSendMailConfirm");
}
});
This will loop through all the checkbox elements inside the table row and will check if it is checked or not and add the appropriate hideForSendMailConfirm class.
Also there is one more issue in your code:
.addClass(".hideForSendMailConfirm");
in order to add a class there is no need to add a . as prefix, we just pass the class name.
But again there is no need of looping here, you can just do this:
$(".modtagerRow :checkbox:checked").closest('tr').addClass('hideForSendMailConfirm');
As, when we call methods of a jQuery object, the elements referred to by the selector we passed to $() are looped through automatically and implicitly. Therefore, we can usually avoid explicit iteration, such as a each() loop here.

Making multiple elements with jquery each() and jquery function

Well, I have a table with multiple text nodes I'm getting through the .text() function and linking to another table with one row that I'm using as a timeline.
I tried to input in a single td of the text values that corresponds to the correct data, but I only managed to grab the last value I in my loop, instead of getting them all. Here is my code:
var tHold, divLine, id, dataTitle, dataDescription;
$(".class1").each(function(){
tHold = $(this);
$(".class2").each(function(){
if ($(this).text() == tHold.attr("value")){
if($('#1').children("div#" + tHold.attr("name")).length == 0){
dataTitle = '<div class="r">' + $(this).text() + '</div><br/>';
dataDescription = '<div class="t">' + $(this).parent().children(".x").text() + ': ' + $(this).parent().children(".y").text() + ' (' + $(this).parent().children(".z").text() + ')' + '</div>';
divLine = $('<div id="' + tHold.attr("name") + '" class="b" value="' + tHold.attr("value") + '"></div>');
divLine.append(dataTitle);
divLine.append(dataDescription);
$("#1").append(divLine);
}
if($('#2').children("div#id" + tHold.attr("name")).length == 0){
dataTitle = '<div class="r">' + $(this).text() + '</div><br/>';
dataDescription = '<div class="t">' + $(this).parent().children(".x").text() + ': ' + $(this).parent().children(".y").text() + ' (' + $(this).parent().children(".z").text() + ')' + '</div>';
divLine = $('<div id="des' + tHold.attr("name") + '" class="c" value="' + tHold.attr("value") + '"></div>');
divLine.append(dataTitle);
divLine.append(dataDescription);
$("#2").append(divLine);
}
}
});
});
It's been simplified and cut out of a whole context , but all that matters is there. How can I set dataDescription to be multiple divs with diferent values instead of just the last I loop through?

Categories