How would you access a specific cell of a dynamically generated table? - javascript

Say I have a table that is generated dynamically:
{% for r in result %}
<tr>
<td>
<form action="/deleteBook" method="POST">
<input type="submit" id="deleteBtn" value="Delete"/>
</form>
</td>
<td>
<form action="/editBook" method="POST">
<input type="submit" id="editBtn" value="Edit"/>
</form>
</td>
<td id="itemID">{{r.itemID}}</td>
<td> {{r.title}}</td>
</tr>
{% endfor %}
Now I want to access the itemID of the row where the respective form submit button was pressed. I know the way I have it set up, every single row will have a column with an id "itemID", I just want to know if it's possible to easily reference the rows even if they don't have unique ID's.

Your event handler receives an Event object, which has two properties:
target, which is the element that clicked
currentTarget, which is the element you hooked the event on (which may be an ancestor of target)
I'd probably use event delegation here, hooking click on the table or tbody, so currentTarget would be the table not not particularly helpful, but target will be the button. From the button you can find the row (tr), and then within the row you can find the td for the item.
I'd get rid of all of those ids, though, since ids are required to be unique on the page. Use class names instead. So:
document.getElementById("id-for-the-table").addEventListener("click", function(event) {
const item = event.target.closest("tr").querySelector(".itemID");
// ...use `item` here... For instance, `item.textContent` will be the item ID
});
Live Example:
document.getElementById("the-table").addEventListener("click", function(event) {
const item = event.target.closest("tr").querySelector(".itemID");
// ...use `item` here... For instance, `item.textContent` will be the item ID
console.log("Item ID: " + item.textContent);
});
// Just for the example, I prevent forms being submitted
document.getElementById("the-table").addEventListener("submit", function(event) {
event.preventDefault();
});
<table id="the-table">
<tbody>
<tr>
<td>
<form action="/deleteBook" method="POST">
<input type="submit" class="deleteBtn" value="Delete"/>
</form>
</td>
<td>
<form action="/editBook" method="POST">
<input type="submit" class="editBtn" value="Edit"/>
</form>
</td>
<td class="itemID">1</td>
<td> Title 1</td>
</tr>
<tr>
<td>
<form action="/deleteBook" method="POST">
<input type="submit" class="deleteBtn" value="Delete"/>
</form>
</td>
<td>
<form action="/editBook" method="POST">
<input type="submit" class="editBtn" value="Edit"/>
</form>
</td>
<td class="itemID">2</td>
<td> Title 2</td>
</tr>
<tr>
<td>
<form action="/deleteBook" method="POST">
<input type="submit" class="deleteBtn" value="Delete"/>
</form>
</td>
<td>
<form action="/editBook" method="POST">
<input type="submit" class="editBtn" value="Edit"/>
</form>
</td>
<td class="itemID">3</td>
<td> Title 3</td>
</tr>
</tbody>
</table>
Note that that uses the new(ish) closest method on Element. If you need to support obsolete browsers like IE, you can polyfill it.
Also note that I've used ES2015+ (const), but if (again) you need to support obsolete browsers, you can use var there instead.

Related

Unable to use .find() to get value from table/form

Trying to wrap my head around this for a while now. Some guru needs to help me out, it would be greatly appreciated. I don't know why it is not working.
$(".form").on('submit', function(event) {
event.preventDefault(); //prevent the forms default action
var surname = $(this).find(".surname");
console.log(surname);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<form class="form" method="post" action="nextpage.php">
<tr>
<td class="name">john</td>
<td class="surname">smith</td>
<td>british</td>
<td><button type="submit" class="btn btn-info btn-sm">Submit</button></td>
</tr>
</form>
<form class="form" method="post" action="nextpage.php">
<tr>
<td class="name">bob</td>
<td class="surname">doe</td>
<td>american</td>
<td><button type="submit" class="btn btn-info btn-sm">Submit</button></td>
</tr>
</form>
</table>
So if i click on the first submit button i should see john, and the second, bob.
As statet in the comments your HTML semantics is wrong. That's the first reason why it doesn't work. The second thing is you might want to use jQuerys .text() to get the "value" of a HTML element.
To make it work, see the example <table> element is now moved inside the <form> element. Depending on your needs this is one possible solution.
$(".form").on('submit', function(event) {
event.preventDefault(); //prevent the forms default action
var surname = $(this).find(".surname");
console.log(surname.text()); // here .text() is the only change in your js code
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="form" method="post" action="nextpage.php">
<table>
<tr>
<td class="name">john</td>
<td class="surname">smith</td>
<td>british</td>
<td><button type="submit" class="btn btn-info btn-sm">Submit</button></td>
</tr>
</table>
</form>
<form class="form" method="post" action="nextpage.php">
<table>
<tr>
<td class="name">bob</td>
<td class="surname">doe</td>
<td>american</td>
<td><button type="submit" class="btn btn-info btn-sm">Submit</button></td>
</tr>
</table>
</form>
Read more about permitted elements inside the <table> element here: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table
Read more about permitted elements inside <form> tag here:
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
I fixed your code:
The <form> wraps around the <table>
Catch the clicks on <buttons> and get the surname relatively to the clicked row (<tr>)
$("button[type=submit]").on('click', function(event) {
event.preventDefault(); //prevent the forms default action
var surname = $(this).closest('tr').find(".surname");
console.log(surname.text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="form" method="post" action="nextpage.php">
<table>
<tr>
<td class="name">john</td>
<td class="surname">smith</td>
<td>british</td>
<td><button type="submit" class="btn btn-info btn-sm">Submit</button></td>
</tr>
<tr>
<td class="name">bob</td>
<td class="surname">doe</td>
<td>american</td>
<td><button type="submit" class="btn btn-info btn-sm">Submit</button></td>
</tr>
</table>
</form>
JSFiddle: https://jsfiddle.net/v9k3sL1f/
just put the class="form" and action inside the tr tag and it'll works.

HTML Submit table dependent upon checkbox

I have a table that is paginated that will allow end users to modify inline in the table itself.
I am using a submit button that redirects and saves the input with SSJS.
My table could potentially have 5k+ records and the table will be paginated.
I would like to only update records that have a checkbox that is checked.
I am using this link to test
https://www.w3schools.com/html/tryit.asp?filename=tryhtml_form_submit
with this code:
<!DOCTYPE html>
<html>
<body>
<h2>HTML Forms</h2>
<form action="/action_page.php">
<table>
<tr>
<td>
Check for save
</td>
<td>
First name
</td>
<td>
Last Name
</td>
</tr>
<tr>
<td>
<input type="checkbox" id="horns" name="feature" value="horns" />
</td>
<td>
<input type="text" name="firstname" value="Mic1key">
</td>
<td>
<input type="text" name="lastname" value="Mouse">
</td>
</tr>
<tr>
<td>
<input type="checkbox" id="horns" name="feature" value="horns" />
</td>
<td>
<input type="text" name="firstname" value="Mic1key">
</td>
<td>
<input type="text" name="lastname" value="Mouse">
</td>
</tr>
</table>
<input type="submit" value="Submit">
</form>
</body>
</html>
so this works because in the SSJS we can check which ones have a value of checked but I have a fear of performance issues once 5k+ records are within the table.
Is there anyway to just submit just the records where the checkbox is checked? or is there any ulterior logic?
If you are only wanting the form to submit when the checkbox is checked, you can add an event listener for the 'submit' event and prevent default if the checkbox is unchecked like so:
let submitButton = document.getElementById('mySubmitBtn');
let checkbox = document.getElementById('myCheckbox');
submitButton.addEventListener('submit', function(e){
if(!checkbox.checked){
e.preventDefault();
}
});
This way the form will only submit if the checkbox is checked.
This question looks like it was addressed here Submit only non empty inputs

Form dynamic added element, and send like array, but the index's are not maintained

I have a form and the elements are added dynamically
<form action="somepage.php">
<table id="content">
</table>
</form>
Via two inputs I accept two values
<input type="text" name="title" id="title">
<input type="text" name="content" id="content">
When I add a element via javascript then the form is like this
<form action="somepage.php">
<table id="content-main">
<tr>
<td>This is a title
<input type="hidden" value="This is a title" name="titles[0]">
Remove
</td>
<td>This is a content
<input type="hidden" value="This is a content" name="content[0]">
Remove
</td>
</tr>
</table>
</form>
Then the elements are saved in "titles" array and "content" array, see there is a button with the class "remove", this is an option that remove the elements if the user have a mistake and need to delete the element
The point, is when there are element added and elements deletes, the content of the form, as an example:
<form action="somepage.php">
<table id="content">
<tr>
<td>This is a title
<input type="hidden" value="This is a title" name="titles[0]">
Remove
</td>
<td>This is a content
<input type="hidden" value="This is a content" name="content[0]">
Remove
</td>
</tr>
<tr>
<td>This is a title
<input type="hidden" value="This is a title" name="titles[3]">
Remove
</td>
<td>This is a content
<input type="hidden" value="This is a content" name="content[3]">
Remove
</td>
</tr>
<tr>
<td>This is a title
<input type="hidden" value="This is a title" name="titles[6]">
Remove
</td>
<td>This is a content
<input type="hidden" value="This is a content" name="content[6]">
Remove
</td>
</tr>
</table>
</form>
The user has remove the element 2,4,5
Like see, the index are different, the way that I imagine, is when delete a element, via Javascript re-index all element, but I don't known if this is the right way.
For add the elements via Javascript I use jQuery and Underscore templates:
<script>
var title = $("#title").val();
var content = $("#content").val();
var index = 0;
var tmpl = _.template($("#template").html());
$("#content-main").append(tmpl({ title: title, content: content, index: index++});
</script>

accessing html table elements in javascript

I would like to access the html input tag which is present inside a table inside a form as shown below. I have used the function below to access the element but I'm getting undefined in the output:
function checkForm()
{
var table=document.getElementById('register').getElementsByTagName('myTab');
document.writeln(table);
}
The above function returns undefined. Why, and how can it be fixed to return the input that I need?
<!DOCTYPE HTML>
<HEAD>
<META CHARSET = "utf-8">
<TITLE>Register</TITLE>
<link rel="stylesheet" type="text/css" href="reglog.css">
</HEAD>
<BODY>
<h1 align=center>Register with our portal</h1>
<FORM id="register" onsubmit="return checkForm();" METHOD="POST">
<table name="myTab" border = 0 align=center>
<tr >
<td> Username </td>
<td> </td>
<td><input name="username" class=textbox type = text required></td>
</tr>
<tr >
<td> Password </td>
<td> </td>
<td><input name="passwd" class=textbox type = password required></td>
</tr>
<tr >
<td> Confirm Password </td>
<td> </td>
<td><input name="c_password" class=textbox type = password required></td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> <input class=button type = submit value = Register> </td>
</tr>
</table>
</FORM>
</BODY>
</HTML>
Javascript's getElementsByTagName function works, as it's name says, with html tag names (div, table, form, etc). In your case would be getElementsByTagName('table'). Instead you could use getElementsByName.
To get the table element with attribute myTab from the element with id register, you can chain a querySelectorAll() method to a getElementById() :
table = document.getElementById('register').querySelectorAll('table[name=myTab]')[0];
console.log(table)
<h1 align=center>Register with our portal</h1>
<FORM id="register" onsubmit="return checkForm();" METHOD="POST">
<table name="myTab" border=0 align=center>
<tr>
<td> Username </td>
<td> </td>
<td><input name="username" class=textbox type=t ext required></td>
</tr>
<tr>
<td> Password </td>
<td> </td>
<td><input name="passwd" class=textbox type=p assword required></td>
</tr>
<tr>
<td> Confirm Password </td>
<td> </td>
<td><input name="c_password" class=textbox type=p assword required></td>
</tr>
<tr>
<td> </td>
<td> </td>
<td> <input class=button type=s ubmit value=R egister> </td>
</tr>
</table>
</FORM>
Note that getElementsByTagName() get the elements from their name, not from their name attribute.
There are various ways to access form elements. In your code you can access form elements using
var x = document.getElementById("register").elements;
This will give you all the elements in your form. However if you want to access first element you can use something like below code
document.getElementById("register").elements[0].value // 0 is the index as per all the elements present in your form 'register'

Use href to submit into a php file

I want to make a login form which should provide 2 ways to submit , one through the login button which should submit the info into the login.php and another through the href (Forgot password) which should redirect the user and submit the info to the forgotpassword.php file. So far I have tried this code but it doesn't work:
<script type="text/javascript">
function forgotpassword()
{
document.getElementById("ee").action="project_forgotpassword.php";
document.getElementById("ee").submit();
}
</script>
<form id="ee" method="POST" action="login.php">
<table>
<tr>
<th>Username</th>
<td><input type="text" name="username"></td>
</tr>
<tr>
<th>Password</th>
<td><input type="password" name="password"></td>
</tr>
<tr>
<th>Forgot Password</th>
</tr>
<tr>
<td></td>
<td>
<input type="submit" name="submit" value="Submit">
</td>
</tr>
</table>
</form>
First issue as I have commented was the typo mistake.
Second issue is submit button name. Refer to following post.
JSFiddle
Code
function forgotpassword() {
var form = document.getElementById("ee");
form.action = "project_forgotpassword.php";
console.log(form)
form.submit();
}
<form id="ee" method="POST" action="login.php">
<table>
<tr>
<th>Username</th>
<td>
<input type="text" name="username">
</td>
</tr>
<tr>
<th>Password</th>
<td>
<input type="password" name="password">
</td>
</tr>
<tr>
<th>Forgot Password
</th>
</tr>
<tr>
<td></td>
<td>
<input type="submit" name="btnSubmit" value="Submit">
</td>
</tr>
</table>
</form>
Changes
<input type="submit" name="btnSubmit" value="Submit">
When calling the javascript function you can omit the javascript: from the onclick handler. You might wish to use that syntax when invoking the function from a standard hyperlink, such as <a href='javascript:func()'>link</a> but that is not common.
In the amended forgotpassword function I use setAttribute rather than trying to call the attribute directly - I think it is more reliable that way. Also, unless in the js function, you prevent the default action of the hyperlink it will simply try to go to the value in the href attribute.
<script type="text/javascript">
/*
function forgotpassword(){
document.getElementById("ee").action="project_forgotpassword.php";
document.getElementById("ee").submit();
}
*/
/* I would tend to use this approach to setting an attribute */
function forgotpassword(){
var form=document.getElementById("ee");
form.setAttribute('action','project_forgotpassword.php');
form.submit();
}
</script>
<form id="ee" method="POST" action="login.php">
<table>
<tr>
<th>Username</th>
<td><input type="text" name="username"></td>
</tr>
<tr>
<th>Password</th>
<td><input type="password" name="password"></td>
</tr>
<tr>
<th>Forgot Password</th>
</tr>
<tr>
<td></td>
<td>
<input type="submit" name="subform" value="Submit">
</td>
</tr>
</table>
</form>
One final thing - change the name of the submit button ~ it shouldn't be called submit - especially when trying to invoke form submission using javascript.
Try this,
$('#forgetpassword').click(function(){
$("form[name='form_name']").attr("action", "project_forgotpassword.php");
$("form[name='form_name']").submit();
});
Change the forget Password link as below,
<a id="forgetpassword">Forgot Password</a>

Categories