Add button with function call for generatet table - javascript

I´m filling a table with jquery from a JSON data source
var data = dataJSONMOV,
fragment = document.createDocumentFragment(),
tr, td, i, il, key;
for(i=0, il=data.length;i<il;i++) {
tr = document.createElement('tr');
for(key in data[i]) {
td = document.createElement('td');
td.appendChild( document.createTextNode( data[i][key] ) );
tr.appendChild( td );
}
//Button generation code should go here (see below)
fragment.appendChild( tr );
}
$('#mytable tbody').append( fragment.cloneNode(true) );
I want to add a button in the end of each row which calls a function displayInformation(string ID) with a parameter from the first coloumn of that row.
How can I accomplish that?
I tried it with this code but it doesn`t show me any buttons
//Button generation code
var btn = document.createElement('input');
btn.type = "button";
btn.className = "btn";
btn.value = data[i][0];
btn.onclick = (getTestAlert(data[i][0]));
tr.appendChild(btn);

You are on right direction on how add the button. You can add it and them add an event listener to the table:
$('#mytable').on("click", "input", function() {
});
// Or
$('#mytable').on("click", "input", getTestAlert);
So, to know what id it belongs, add a data attribute:
var btn = document.createElement('input');
btn.dataset.id = data.id;
And how to retrieve it:
$('#mytable').on("click", "button", function() {
var id = $(this).data("id"); // For jQuery
id = this.dataset.id; // For vanilla
});
Your loop would probably end like this:
for(i=0, il=data.length;i<il;i++) {
tr = document.createElement('tr');
for(key in data[i]) {
td = document.createElement('td');
td.appendChild( document.createTextNode( data[i][key] ) );
tr.appendChild( td );
}
// Add button in last column
var btn = document.createElement('input');
btn.type = "button";
btn.className = "btn";
btn.value = data[i][0];
btn.onclick = (getTestAlert(data[i][0]));
tr.appendChild(btn);
fragment.appendChild( tr );
}
Working demo
Besides, I don't know if its some kind of a requirement, but if you're using jQuery, you should use it for your entire code, like the elements creating as well. Creating elements may be odd in some browsers and jQuery takes care of it. If you're interested, your code should became something like:
var data = dataJSONMOV,
fragment = document.createDocumentFragment(),
key, html = "";
for(var i=0, il=data.length;i<il;i++) {
html+= "<tr>";
for(key in data[i]) {
html+= "<td>" + data[i][key] + "</td>";
}
html+= "<td><input type='button' class='btn' value='Click me' data-id='" + data[i].id + "' /></td></tr>";
}
$("#mytable").append(html);
Pretty short, huh ?

Because you're populating the table dynamically, you need to add a click listener based on some parent defined in the html. Assuming this is the case for '#myTable tbody' and that the parameter from the first column of that row that you need for displayInformation() is accessible via .text(), you could use
$(document).ready(function() {
$('#myTable tbody').on('click', 'input[type="button"]', function() {
displayInformation($('td:first-child', $(this).parents('tr')).text());
});
});
to create the click listener for the row's button.

Related

Adding button that removes object from array inside a table

Created a form and empty table, trough DOM i should create a new object from class Movie and insert it in empty table with a button to remove it.
Don't know how i would create the button with a function to remove the movies[i] in the table. Sorry I am still learning and don't know how to express my problems.
window.onload = function(){
let frmMovies = document.getElementById("frmMovies");
let txtTitle = document.getElementById("txtTitle");
let txtYear = document.getElementById("txtYear");
let txtGender = document.getElementById("txtGender");
frmMovies.addEventListener("submit", function (event) {
let newMovie = new Movies(txtTitle.value, txtYear.value, txtGender.value);
movies.push(newMovie);
refreshTable();
/*let btn = document.getElementsByClassName("btn");
btn.addEventListener("click", function (event) {
movies.splice(x, 1);
event.preventDefault();
})*/
event.preventDefault();
})
}
function refreshTable() {
let movieTable = document.getElementById("movieTable");
let txt = "";
txt = "<tr><th>TÍTULO</th><th>ANO</th><th>GÉNERO</th><th>!</th></tr>";
for(let i = 0 ; i < movies.length; i++){
txt += "<tr>";
txt += "<td>" + movies[i].title + "</td>";
txt += "<td>" + movies[i].year + "</td>";
txt += "<td>" + movies[i].gender + "</td>";
txt += "<td>" + "<button class='btn'>" + "Remove" + "</button>" + "</td>";
txt += "</tr>";
}
movieTable.innerHTML = txt;
}
You could add an onclick attribute to your Remove buttons when you build it. Upon clicking on the button, it will call a function passing current button element i.e. this.
let movies = [];
// etc
function refreshTable() {
let movieTable = document.getElementById("movieTable");
let txt = "";
txt = "<tr><th>TÍTULO</th><th>ANO</th><th>GÉNERO</th><th>!</th></tr>";
for(let i = 0 ; i < movies.length; i++){
txt += "<tr>";
txt += "<td>" + movies[i].title + "</td>";
txt += "<td>" + movies[i].year + "</td>";
txt += "<td>" + movies[i].gender + "</td>";
txt += "<td>" + "<button type='button' class='btn' onclick='deleteRow(this)'>" + "Remove" + "</button>" + "</td>";
txt += "</tr>";
}
movieTable.innerHTML = txt;
}
Create your new function which will delete the current row using .removeChild().
function deleteRow(button) {
let row = button.parentElement.parentElement;
document.getElementById("movieTable").removeChild(row);
}
This is untested of course but you could do something like this.
Event Delegation is the most efficient way of using one element to listen for an event for multiple child/descendant elements. Simply find an ancestor (tbody) element that the group of target elements (buttons) have in common.
Demo
// Reference the <tbody> by its tagName
var tbody = document.querySelector('tbody');
// Register the click event on <tbody> calls removeRow when clicked
tbody.addEventListener('click', removeRow, false);
// Pass through the Event Object
function removeRow(event) {
/* Event Object property Event.target always knows which
|| element was actually clicked. Use event.target to compare
|| or assert a true/false check in order to target the rest of
|| the DOM in reference to event.target.
|| Find the closest <tr> from event.target
|| `this` is the function owner <tbody> which removes the <tr>
*/
if (event.target.className === 'btn') {
var row = event.target.closest('tr');
this.removeChild(row);
}
return false;
}
<table>
<tbody>
<tr>
<td>Reservoir Dogs</td>
<td>1992</td>
<td>Male?</td>
<td><button class='btn'>Remove</button></td>
</tr>
<tr>
<td>The Usual Suspects</td>
<td>1995</td>
<td>Male?</td>
<td><button class='btn'>Remove</button></td>
</tr>
<tr>
<td>Pulp Fiction</td>
<td>1994</td>
<td>Male?</td>
<td><button class='btn'>Remove</button></td>
</tr>
<tr>
<td>Sin City</td>
<td>2005</td>
<td>Male?</td>
<td><button class='btn'>Remove</button></td>
</tr>
<tr>
<td>Old Boy</td>
<td>2003</td>
<td>Male?</td>
<td><button class='btn'>Remove</button></td>
</tr>
</tbody>
</table>
Since you're new to this, I would recommend really focusing on understanding the difference between an actual DOM element and the HTML tags that are used to create them.
The DOM is the actual mechanism that determines what is displayed on the page. HTML is just a way of serializing a DOM into text, so you can easily send it over networks to other computers. A web browser parses HTML and recreates the DOM on the client's computer.
The DOM consists of JavaScript objects that you can manipulate with Javascript. When you set movieTable.innerHTML, what you're doing is telling the browser: to do the following:
Parse the assigned string as HTML.
Delete all of the children of movieTable.
Add the new DOM elements parsed from the assigned string as children of movieTable.
This is wasteful because you're recreating the entire table every time you do it, even though you may only be adding or removing a single element. It also can be frustrating to maintain, since JS does not play well with long string literals. This is one of the reasons why stuff like this is often handled by templating libraries.
I'll keep it simple though, and show you how you can do this with just the standard DOM methods:
let frmMovies = document.getElementById("frmMovies");
let txtTitle = document.getElementById("txtTitle");
let txtYear = document.getElementById("txtYear");
let txtGender = document.getElementById("txtGender");
// You don't need to keep getting this every time.
// Just get it once and reuse the reference.
let movieTable = document.getElementById("movieTable");
frmMovies.addEventListener("submit", function (event) {
// You can do this anytime, as long as you do it before your
// handler returns. I usually do it right away.
event.preventDefault();
// First, let's create a new table row.
let movieRow = document.createElement("tr");
// Create the title cell.
let titleCell = document.createElement("td");
titleCell.innerText = txtTitle.value;
// Create the year cell.
let yearCell = document.createElement("td");
yearCell.innerText = txtYear.value;
// Create the gender cell.
let genderCell = document.createElement("td");
genderCell.innerText = txtGender.value;
// Create the remove button and a cell to put it in.
let buttonCell = document.createElement("td");
let removeButton = document.createElement("button");
removeButton.innerText = 'Remove';
// Attach the click handler for the remove button.
removeButton.addEventListener("click", function() {
// This handler will form a *closure*, which will store the
// reference to the movieRow, enabling you remove it by simply
// calling `remove` on it.
movieRow.remove();
});
// Now, let's put it all together:
// Add the remove button to its cell.
buttonCell.appendChild(removeButton);
// Add the cells to the table row.
movieRow.appendChild(titleCell);
movieRow.appendChild(yearCell);
movieRow.appendChild(genderCell);
movieRow.appendChild(buttonCell);
// Add the table row to the table.
movieTable.appendChild(movieRow)
});
MDN has some pretty solid documentation of standard HTML DOM that you'll probably want to check out:
https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model

link a checkbox to an object in Javascript

Suppose I have a table which is populated by filling out a form on a page and clicking the submit button.
The last column of the table is a Completed section with a checkbox on each row. On clicking on the checkbox I want to change the .completed property from false to true on that object.
How can I distinguish which checkbox was clicked and change the property from that row?
this.addRowToTable = function() {
return "<tr id='tableRow'><td>" + this.app + "</td><td>" + this.priority + "</td><td>" + this.date + "</td><td>" + this.additionalNotes + "</td><td>" + "<input type='checkbox' class='checkApp[]' value='" + this.completed + "' />" + "</td></tr>";
};
I have all the checkboxes in the checkApp array, but Im not sure where to go from there?.
This is called when the form is submitted:
function addAppointment() {
if (txtApp.value == "" || txtPriority.value == "" || txtDate.value == "" || {
alert("Please fill all text fields");
} else {
var app = new Appointment(txtApp.value, txtPriority.value, txtDate.value, txtNotes.value, false);
apps.push(app);
localStorage.setItem("apps", JSON.stringify(apps));
clearUI();
}
updateTable();
updateTable() loops through all objects in my array and adds them between table tags:
for (var i = 0; i < apps.length; i++) {
var app = new Appointment(apps[i].app, apps[i].priority, expenses[i].date, apps[i].notes, false);
tblHTML += app.addRowToTable();
}
My Appointment Object:
function Appointment(app, priority, date, notes, completed) {
this.app = app;
this.priority = priority;
this.date = date;
this.additionalNotes = notes;
this.completed = completed;
this.addRowToTable = function { ... };
}
First of all, in HTML, id attributes should be unique. So, make sure table rows have unique IDs. At the moment, all of them have the identical ID of tableRow.
Besides, you should consider using a framework/library such as jQuery for real-world scenarios rather than creating the DOM elements, etc. manually.
Now back to the original problem: if you use the DOM API rather than string concatenation to create the table rows, you can add custom fields to the DOM objects representing the table rows. So, from each table row, you can have a reference back to its corresponding Appointment object:
var row = document.createElement("tr");
row.appointment = this;
Similarly, you can use the DOM API to create the table cells as well as the checkbox:
addTd(row, this.app);
addTd(row, this.priority);
addTd(row, this.date);
addTd(row, this.additionalNotes);
var input = document.createElement("input");
var td = document.createElement("td");
td.appendChild(input);
row.appendChild(td);
input.setAttribute("type", "checkbox");
input.setAttribute("class","checkApp[]"); // Why checkApp[]? checkApp or check-app make more sense
input.setAttribute("value", this.completed);
where addTd is the following function:
function addTd(row, innerHTML) {
var td = document.createElement("td");
td.innerHTML = innerHTML;
row.appendChild(td);
}
Now that you are using the DOM APIs, you can easily attach event listeners to each checkbox object as well.
Then inside the event listener you can get a reference back to the Appointment corresponding to the row you
have changed its checkbox:
var row = document.createElement("tr");
row.appointment = this;
addTd(row, this.app);
addTd(row, this.priority);
addTd(row, this.date);
addTd(row, this.additionalNotes);
var input = document.createElement("input");
var td = document.createElement("td");
td.appendChild(input);
row.appendChild(td);
input.setAttribute("type", "checkbox");
input.setAttribute("class","checkApp[]"); // Why checkApp[]? checkApp or check-app make more sense
input.setAttribute("value", this.completed);
input.addEventListener("change", function(event) {
var row = this.parentNode.parentNode,
appointment = row.appointment;
// change appointment however you like
});

jQuery: dialog() of table data from ajax not showing

$(function () {
$('.referral').on('click', function () {
$('#hold').html($(this).find('DIV').html());
$('#hold').dialog();
});
});
$(function getTableData() {
$.ajax({
url: 'interface_API.php',
data: "",
dataType: 'json',
success: function (data) {
setTimeout(function () {
getTableData()
}, 1000);
var body = document.getElementById('tbody');
body.innerHTML = '';
for (var i in data) {
var row = data[i];
var customerCode = row.CustomerCode;
var phone = row.PhoneNumber;
var thetime = row.TimeStamp;
var tr = document.createElement('TR');
tr.className += " " + "referral";
body.appendChild(tr);
var td = document.createElement('TD');
td.appendChild(document.createTextNode(customerCode));
tr.appendChild(td);
var td = document.createElement('TD');
td.appendChild(document.createTextNode(phone));
tr.appendChild(td);
var td = document.createElement('TD');
td.appendChild(document.createTextNode(thetime));
tr.appendChild(td);
var tr2 = document.createElement('TR');
body.appendChild(tr2);
var td2 = document.createElement('TD');
var divE = document.createElement('DIV');
divE.className += " " + "extra";
var text = document.createTextNode("sage, extra, etc");
divE.appendChild(text);
td2.appendChild(divE);
tr2.appendChild(td2);
}
}
});
});
I have data from a JSON api that is imported using ajax.
This is displayed to a table, of which the rows are created using JS.
With each row, there is an additional row of 'additional' data that is hidden from the user.
on click of a row, i wish for a dialog to appear displaying this 'additional' data.
Initally i tryed todo this with writing out the rows in "raw format" (var row = "<tr><td>...</td></tr>" etc) however i read that this does not work well with javascript functions like the one i am trying to execute as the DOM has already been set (i'm not 100% sure about that). This is why i use JS to create each element & do it correctly, to some respect.
However, i am still unable to get the dialog to appear
Notes.
below the table (html hard coded) is a empty div which is used as a holder for when a dialog is to appear.
I have had success before when the data is static & ajax is not involved
I found the solution.
It seems that the JS .on('click', function() was not being called, or registered at the right point. i checked on the DOM properties using chrome dev tools & .referral's onclick property was null.
Instead, i set the onclick attribute of each <TR> with the function clicks() like so:
var tr = document.createElement('TR');
tr.setAttribute("onclick", "clicks(this)");
With,
function clicks(param){
$('#hold').html($(param).find('DIV').html());
$('#hold').dialog();
};

HTML Table content insert and clear using javascript

I have a table and assigned a id to it. Initially there is no content.i.e., just the table tag.
I am using this to clear the table contents
function emptyTable ( tableRef )
{
var resultCount = tableRef.rows.length;
for ( var i=0; i<resultCount; i++)
{
if ( tableRef.rows[tableRef.rows.length-1].cells[0].tagName == "TD" )
{
tableRef.deleteRow(tableRef.rows.length-1);
}
}
}
tableRef will have the table id. For first time i have clear the table and the rows are inserted.
var resultListRef = document.getElementById("showReferencesDet");
var row = resultListRef.insertRow(0);
var newCell = row.insertCell(0);
newCell.innerHTML = 'Select';
var newCell2 = row.insertCell(1);
newCell2.innerHTML = 'Reference Number';
var row = resultListRef.insertRow(resultListRef.rows.length);
var newCell = row.insertCell(0);
name="referenceId" value="' + id + '" />';
newCell.innerHTML = '<input type="checkbox" id="referenceId" name="referenceId" value="' + allVars + '" />';
var newCell2 = row.insertCell(1);
newCell2.innerHTML = RefNo;
It works for the first time but didn't works in the 2nd time.
Please help to solve it.
just change your for loop
function emptyTable ( tableRef )
{
document.getElementById(tableRef).innerHTML='';
}
Instead of:
var row = resultListRef.insertRow(resultListRef.rows.length);
you can do:
var row = resultListRef.insertRow(-1);
and the row will be inserted as the last row.
Removing the rows of a table doesn't necessarily remove all content, it may still contain empty text nodes, thead and tfoot elements, etc. Consider:
function emptyTable ( tableRef ) {
while (tableRef.firstChild) {
tableRef.removeChild(tableRef.firstChild);
}
}
That will clear everything from inside the table (but not properties and attributes of the table itself) as if you had <table ... ></table>.
However, you may want to keep header rows and footers. In that case, you just want to remove the tBody elements:
function emptyTableBodies ( tableRef ) {
var tBodies = tableRef.tBodies;
for (var i=tBodies.length; i;) {
tableRef.removeChild(tBodies[--i]);
}
}
so you can do:
<table id="t0">
<thead>
<tr><th>head
</thead>
<tr><td>0
<tr><td>0
<tr><td>0
<tr><td>0
</table>
<button onclick="emptyTableBodies(document.getElementById('t0'))">Empty table bodies</button>
Note that a table with no content is not valid, so fix that as soon as you can after the above.

attaching JS functions to dynamically created object events

I use following code to dynamically add rows to my ASP.NET table. I create a span, then fill it with an html textbox code to create some textboxes in my row, now I'm going to attach some functions to my textbox events, for instant blur or keypress event:
var TR = document.createElement('tr');
TR.style.textAlign = 'center';
//mission end date
var TD = document.createElement('td');
var span = document.createElement("span");
span.innerHTML = "<input maxlength='5' type='text' width='50px' style='width:50px;' value=''/>";
TD.appendChild(span);
TR.appendChild(TD);
.......
TR.appendChild(TD);
document.getElementById('<%=tblData.ClientID %>').appendChild(TR);
I've create some other javascript functions that I'd like to attach them to these dynamically created textbox events, for instance:
function onBlur(){
.....
}
how can I attach onBlur to onblur event of these dynamically created objects?
thanks
replace
span.innerHTML = "<input maxlength='5' type='text' width='50px' style='width:50px;' value=''/>";
with
var input = document.createElement("input");
input.style.width="50px";
input.type="text";
input.onblur = your_function_handler;
span.appendChild(input);

Categories

Resources