As simple as it is, the idea of my question is that I have an array of JSON objects, I want to dynamically append these objects to an HTML table, and in the last td
I want to add a remove button so I can remove the row.
Actually I've spend several days looking for an efficient solution but unfortunately didn't find anything.
I've tried to do it in my own and this is what I came up with:
for (var i = 0; i < objArr.length; i++) {
var tr = "<tr>";
var td1 = "<td>" + objArr[i]["empID"] + "</td>";
var td2 = "<td>" + objArr[i]["fname"] + "</td>";
var td3 = "<td>" + objArr[i]["lname"] + "</td>";
var td4 = "<td>" + objArr[i]["phone"] + "</td>";
var td5 = "<td>" + objArr[i]["address"] + "</td>";
var td6 = "<td>" + objArr[i]["deptID"] + "</td>";
var td7 = "<td>" + objArr[i]["email"] + "</td>";
var td8 = "<td>" + '<button id="' + objArr[i]["empID"] + '" value="' + objArr[i]["empID"] + '" onclick="onClickDelete(' + objArr[i]["empID"] + ')">Delete</button>' + "</td></tr>";
$("#dataTable").append(tr + td1 + td2 + td3 + td4 + td5 + td6 + td7 + td8);
}
But as you may notice, this is not the efficient manner to acplish that. I'm pretty sure that definitely there is a better solution for this.
So could anyone please provide any suggestions
As simple as it is, the idea of my question is that I have an array of JSON objects, I want to dynamically append these objects to an HTML table, and in the last td
I want to add a remove button so I can remove the row.
Actually I've spend several days looking for an efficient solution but unfortunately didn't find anything.
I've tried to do it in my own and this is what I came up with:
for (var i = 0; i < objArr.length; i++) {
var tr = "<tr>";
var td1 = "<td>" + objArr[i]["empID"] + "</td>";
var td2 = "<td>" + objArr[i]["fname"] + "</td>";
var td3 = "<td>" + objArr[i]["lname"] + "</td>";
var td4 = "<td>" + objArr[i]["phone"] + "</td>";
var td5 = "<td>" + objArr[i]["address"] + "</td>";
var td6 = "<td>" + objArr[i]["deptID"] + "</td>";
var td7 = "<td>" + objArr[i]["email"] + "</td>";
var td8 = "<td>" + '<button id="' + objArr[i]["empID"] + '" value="' + objArr[i]["empID"] + '" onclick="onClickDelete(' + objArr[i]["empID"] + ')">Delete</button>' + "</td></tr>";
$("#dataTable").append(tr + td1 + td2 + td3 + td4 + td5 + td6 + td7 + td8);
}
But as you may notice, this is not the efficient manner to acplish that. I'm pretty sure that definitely there is a better solution for this.
So could anyone please provide any suggestions
Share Improve this question edited Aug 31, 2016 at 6:22 Mosh Feu 29.4k18 gold badges93 silver badges141 bronze badges asked Aug 31, 2016 at 6:06 Husain AlhamaliHusain Alhamali 8234 gold badges20 silver badges34 bronze badges 1- actually no I'm not using it @AneeshSivaraman – Husain Alhamali Commented Aug 31, 2016 at 6:10
6 Answers
Reset to default 4You just need to pass the event
to the function onClickDelete
so you can get the button with event.target
. Then, you can get the parent tr
using parents('tr')
. Finally, remove it using remove()
function.
I don't know your objArr
so I made it.
var objArr = [
{
empID:'empID1',
fname: 'fname1',
lname: 'lname1',
phone: 'phone1',
address: 'address1',
deptID: 'deptID1',
email: 'email1'
},
{
empID:'empID2',
fname: 'fname2',
lname: 'lname2',
phone: 'phone2',
address: 'address2',
deptID: 'deptID2',
email: 'email2'
}
];
for (var i = 0; i < objArr.length; i++) {
var tr = "<tr>";
var td1 = "<td>" + objArr[i]["empID"] + "</td>";
var td2 = "<td>" + objArr[i]["fname"] + "</td>";
var td3 = "<td>" + objArr[i]["lname"] + "</td>";
var td4 = "<td>" + objArr[i]["phone"] + "</td>";
var td5 = "<td>" + objArr[i]["address"] + "</td>";
var td6 = "<td>" + objArr[i]["deptID"] + "</td>";
var td7 = "<td>" + objArr[i]["email"] + "</td>";
var td8 = "<td>" + '<button id="' + objArr[i]["empID"] + '" value="' + objArr[i]["empID"] + '" onclick="onClickDelete(event, ' + objArr[i]["empID"] + ')">Delete</button>' + "</td></tr>";
$("#dataTable").append(tr + td1 + td2 + td3 + td4 + td5 + td6 + td7 + td8);
}
function onClickDelete(event) {
$(event.target).parents('tr').remove();
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="dataTable"></table>
Also, let my suggest you a better approach (on my opinion) for all your code.
var objArr = [
{
empID:'empID1',
fname: 'fname1',
lname: 'lname1',
phone: 'phone1',
address: 'address1',
deptID: 'deptID1',
email: 'email1'
},
{
empID:'empID2',
fname: 'fname2',
lname: 'lname2',
phone: 'phone2',
address: 'address2',
deptID: 'deptID2',
email: 'email2'
}
];
var html = '';
for (var i = 0; i < objArr.length; i++) {
html = "<tr>";
html += "<td>" + objArr[i]["empID"] + "</td>";
html += "<td>" + objArr[i]["fname"] + "</td>";
html += "<td>" + objArr[i]["lname"] + "</td>";
html += "<td>" + objArr[i]["phone"] + "</td>";
html += "<td>" + objArr[i]["address"] + "</td>";
html += "<td>" + objArr[i]["deptID"] + "</td>";
html += "<td>" + objArr[i]["email"] + "</td>";
html += "<td>" + '<button>Delete</button>' + "</td></tr>";
$("#dataTable").append(html);
}
$('#dataTable').on('click', 'button', onClickDelete);
function onClickDelete() {
$(this).parents('tr').remove();
}
<script src="https://ajax.googleapis./ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="dataTable"></table>
That's way, your code will be cleaner and easy to read.
You could use template, such as underscore.js, mustache or handlebars. This is an example with underscore.
On your HTML add a script tag of type='text/template' and with an id(#row) like this:
<tr> <td><%= name %></td> <td><%= lastName %></td> </tr>
2.Then on javascript:
var obj = [{name:"Diego",lastName:"Gallegos"}, {name:"Juan",lastName:"Perez"}];
for(var i = 0; i < obj.length; i++){
/* Pass the html of the template on step 1 to the _.template function
from underscore (_). Import it from its cdn */
var row = _.template( $('#row').html() );
/* Then to the tbody of the of your table then only append each row
passing the object from the array. row is now a function that
receives an object and piles the template to html */
$('tbody').append(row(obj[i]));
}
This is way better than using strings.
The following solution use DocumentFragment to create your DOM (jQuery it is not necessary).
The template is created using Template literals (ES 6).
DocumentFragments is faster than repeated single DOM node injection and allows to perform DOM node operations (like adding events) on new elements instead of mass-injection via innerHTML. DocumentFragment is a good solution when performing lots of DOM operations which could speed up time if you table is a big one.
var data = [{
empID: 'empID1',
fname: 'fname1',
lname: 'lname1',
phone: 'phone1',
address: 'address1',
deptID: 'deptID1',
email: 'email1'
}, {
empID: 'empID2',
fname: 'fname2',
lname: 'lname2',
phone: 'phone2',
address: 'address2',
deptID: 'deptID2',
email: 'email2'
}];
var temp = document.createElement('table');
var html = '';
html += '<table style="width:100%">';
data.forEach(function(item) {
console.log(item);
html += `<tr>`;
html += `<th>${item.empID}</th>`;
html += `<th>${item.fname}</th>`;
html += `<th>${item.lname}</th>`;
html += `<th>${item.phone}</th>`;
html += `<th>${item.address}</th>`;
html += `<th>${item.deptID}</th>`;
html += `<th>${item.email}</th>`;
html += `<th><button type="button">Remove</button></th>`;
html += `</tr>`;
});
html += `</tr>`;
html += '</table>';
temp.innerHTML = html;
document.getElementById('output').appendChild(temp);
<div id="output">
</div>
The following script instead use string concatenation.
Both solutions append data from a JavaScript object to an HTML table and add a button at the end of each row as for your requirement.
var data = [{
empID: 'empID1',
fname: 'fname1',
lname: 'lname1',
phone: 'phone1',
address: 'address1',
deptID: 'deptID1',
email: 'email1'
}, {
empID: 'empID2',
fname: 'fname2',
lname: 'lname2',
phone: 'phone2',
address: 'address2',
deptID: 'deptID2',
email: 'email2'
}];
var html = '';
html += '<table style="width:100%">';
data.forEach(function(item) {
console.log(item);
html += `<tr>`;
html += `<th>${item.empID}</th>`;
html += `<th>${item.fname}</th>`;
html += `<th>${item.lname}</th>`;
html += `<th>${item.phone}</th>`;
html += `<th>${item.address}</th>`;
html += `<th>${item.deptID}</th>`;
html += `<th>${item.email}</th>`;
html += `<th><button type="button">Remove</button></th>`;
html += `</tr>`;
});
html += `</tr>`;
html += '</table>';
document.getElementById('output').innerHTML = html;
<div id="output">
</div>
please use the following code.
HTML
<table id="dataTable">
<thead>
<tr>
<th>EmpId</th>
<th>fname</th>
<th>lname</th>
<th>phone</th>
<th>address</th>
<th>deptID</th>
<th>email</th>
<th></th>
</tr>
</thead>
</table>
JS
$(document).ready(function() {
objArr = [
{ empID : 1, fname: 'Employee1', lname: 'Last name1', phone : '234242344', address: 'address1', deptID : '1', email : '[email protected]'},
{ empID : 2, fname: 'Employee2', lname: 'Last name2', phone : '234244243', address: 'address2', deptID : '1', email : '[email protected]'}
];
for (var i = 0; i < objArr.length; i++) {
var emp = objArr[i];
$("#dataTable").append("<tr><td>" + emp.empID + "</td><td>" + emp.fname + "</td><td>" + emp.lname + "</td><td>" + emp.phone + "</td> <td>" + emp.address + "</td><td>" + emp.deptID + "</td><td>" + emp.email + "</td><td><button class='delete' id=" + emp.empID +" name=" + emp.fname + ">Delete</button> </td></tr>");
}
$(".delete").click(function(){
if (confirm('Are you sure you want to delete ' + emp.fname + ' ?')) {
var empId = this.id; //for deletion from server
$(this).parent().parent().remove();
}
});
});
CSS
#dataTable td {
padding : 10px;
}
#dataTable th {
padding : 10px;
}
Refer this Fiddle
You might like my solution as well. I am using ES6 template strings, thereby the code is a little bit more readable and concise.
var rowsHtml = data.map(function(row) {
var cellsHtml, row, removeButton = $('<button>', {
text: 'Remove'
});
for (var i in row) if (row.hasOwnProperty(i)) {
cellsHtml += `<td>${row[i]}</td>`;
}
row = $(`<tr>${cellsHtml}</tr>`);
removeButton.click(function() {
row.remove();
});
return row.append(removeButton);
});
$table.append(rowsHtml);
Explanation
Basically I am doing a for loop over your data, but I use a map function instead, cause it returns new array right away.
var numbers = [1, 2, 3];
var newNumbers = [];
for(var i = 0; i < numbers.length; i++) {
newNumbers.push(numbers[i] + 1);
}
// newNumbers = [2, 3 ,4]
var numbers = [1, 2, 3];
var newNumbers = numbers.map(function(number) {
return number + 1;
});
// same result, but seems better for my eyes lol - newNumbers = [2, 3 ,4]
Then in the first line I create a button that is jQuery object using quite straight forward syntax:
$(htmlElement, objectOfProperties);
$('<div>', {
text: 'SomeDiv',
"class": 'foobar' // I wrap class in quotes cause it is a reserved keyword
});
// would create <div class="foobar">SomeDiv</div>, but I can call a jQuery methods on it
Right now in a for-in
loop over single row I create our table cells. This is what you are doing like this:
var td1 = "<td>" + objArr[i]["empID"] + "</td>";
At this point cellsHtml
is just a simple string. As I want to call a jQuery method append
on it I use same approach as when I was creating a removeButton to make flat HTML a jQuery object.
Now I use jQuery click
method passing a handler that on click will remove a row that we are currently dealing with.
At the end I append our button (cause I haven't done it yet, our row contains just table cells with data) and return the row, which is added to our result array (behind the scenes by map function).
First of all if you are using JQuery, its best if you dont use onclick method as we have this
selector in JQuery, you can reduse ur code to the following
for (var i = 0; i < objArr.length; i++) {
var data = "<tr>";
data+= "<tr><td>" + objArr[i].empID + "</td><td>" + objArr[i].fname + "</td><td>" + objArr[i].lname + "</td><td>" + objArr[i].phone + "</td> <td>" + objArr[i].address + "</td><td>" + objArr[i].deptID + "</td><td>" + objArr[i].email + "</td><td><button class='deleteRow' id=" + objArr[i].empID +">Delete</button> </td></tr>";
$("#dataTable").append(data);
}
then later
$(document).delegate(".deleteRow", "click", function(){
$(this).closest("tr").remove();
});
and i think it will be enough for what u need.