How to capture row id from table body click event - javascript

How do you get the id from a row element that has been dynamically created. Below is the code that I have tried but it will not fire the event.
HTML
<table id="tblRawMaterials" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>
A
</th>
<th>
B
</th>
<th>
C
</th>
</tr>
</thead>
<tbody>
<tr id="DCB4325E-951C-67E3-1E8F-7270D488A1EB" >
<td>G20002</td>
<td>1,783</td>
<td>2,000</td>
</tr>
</tbody>
</table>
Script
$("#tblRawMaterials tbody").click( function(e) {
// Here i need to capture row id of clicked cell.
});
Thanks in advance

you need the equivalent (old) sintax of on, exactly the same concept:
$("#tblRawMaterials tbody").delegate('tr', 'click', function(e) {
console.log($(this).attr('id'))
});
You need to use event delegation, in this way the event is attached to the parent tbody and fired anytime that a tr is clicked. It doesn't depend on the tr, so it will work also for elements dynamically added.
Please check che fiddle

You can try like this also with closest
$(document).ready(function() {
$("#tblRawMaterials tbody").click(function(e) {
var $tr = $(e.target).closest('tr'),
rowId = ($tr).attr("id"); // Here you can capture the row id of clicked cell.
alert(rowId);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<table id="tblRawMaterials" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th>
A
</th>
<th>
B
</th>
<th>
C
</th>
</tr>
</thead>
<tbody>
<tr id="DCB4325E-951C-67E3-1E8F-7270D488A1EB">
<td>G20002</td>
<td>1,783</td>
<td>2,000</td>
</tr>
</tbody>
</table>
UPDATE :
If you really need delegate, then you can use the following code snippets.
$(document).ready(function () {
$(document).delegate("#tblRawMaterials tbody", "click", function (e) {
var $tr = $(e.target).closest('tr'),
rowId = ($tr).attr("id"); // Here you can capture the row id of clicked cell.
alert(rowId);
});
});
Note: Here I didn't bind click event for tr element.
Hope this helps!

You need to use event delegation, in this way the event is attached to the parent tbody and fired anytime that a tr is clicked. It doesn't depend on the tr, so it will work also for elements dynamically added.
$("#tblRawMaterials tbody").on('tr','click',function(e) {
var id = $(this).attr('id');
});
use jQuery delegate
Description: Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a
specific set of root elements.
$("#tblRawMaterials tbody").delegate('tr','click',function(e) {
var id = $(this).attr('id');
});

try this
$(document).ready(function () {
$('#tblRawMaterials tr').click(function () {
alert($(this).attr('id'));
});
});

Related

Find Table Row Index for Dynamically Generated Table

Here is my scenario:
I have a table that displays the Name, Age, and Details content on each row. When a user selects the Details button, it should trigger a modal and show additional content specific to that Person in the table.
Issue at hand:
I am using Razor syntax and dynamically generating the rows within the table.
Question: How can I get the row index value for that specific row when selecting the Details button
Additional Notes:
I did some research online, but couldn't find anything that helped me in my scenario.
Html
<div class="col-md-12">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Details</th>
</tr>
</thead>
<tbody>
#foreach (var viewModel in Model)
{
<tr>
<td>#viewModel.Name</td>
<td>#viewModel.Age</td>
<td><button onclick="PersonViewModel(this)" type="button" class="btn btn-success" data-toggle="modal" data-target="#details-modal"><span class="fa fa-external-link-square"></span> Details</button></td>
</tr>
}
</tbody>
</table>
</div>
JavaScript:
function PersonViewModel(x) {
$('body').on('click', 'a.showMore', function(event) {
var rowIndex = $(this).closest('tr').index();
alert("Row index is: " + rowIndex);
});
}
You are binding event in the PersonViewModel click handler. In order to get the index of parent tr, you need to use the x object.
Use
function PersonViewModel(x) {
var rowIndex = $(x).closest('tr').index();
alert("Row index is: " + rowIndex);
}
You can try like this. I think this will help you.
$(this).parents('tr')).index()
This will give you parent tr and index() function will give index of that tr.
Please check my code instead of your
function PersonViewModel(x) {
var index = $(".table tr").index( $(x).parents('tr'));
alert(index);
}

After click on row, remove seletced class from another rows

I have one small problem with my JQuery Code.
I created simple table in HTML.
<table class="table">
<tr>
<th>Name</th>
<th>Surname</th>
<th></th>
</tr>
<tr>
<td>name 1</td>
<td>surname 1</td>
<td>actions</td>
</tr>
<tr>
<td>name 2</td>
<td>surname 3</td>
<td>actions</td>
</tr>
</table>
Then I want to highlight the row in yellow, when I click on this row
So when I am click on row add class "selected" but when I click on another row I have to remove "selected" class from previous row. So I tried create JQuery action
$('tr').not(':first').click(function () {
var table = $(this).closest("table");
var rows = table.children("tr");
alert(rows.length);
rows.each(function () {
$(this).removeClass("selected");
});
$(this).addClass('selected');
});
I tried find closest table from this clicked row and get all children <tr>,
next in loop remove "selected" class and add to clicked row this class.
But always alert(rows.length) return me 0 rows :<
Please help me.
Thanks.
why not simply
$('tr').not(':first').click(function () {
$(this).addClass("selected"); //add class selected to current clicked row
$(this).siblings().removeClass( "selected" ); //remove class selected from rest of the rows
});
First remove class from the selected one, then add the class to the new one.
$('tr').not(':first').click(function () {
$('tr.selected').removeClass("selected");
$(this).addClass('selected');
});
Write this:
$('.table tr').not(':first').on('click', function(){
$('.table tr').removeClass('selected');
$(this).addClass('selected');
});
As per your question, write like this:
var rows = $(this).siblings("tr");
Instead of:
var rows = table.siblings("tr");

plain text to input text on click using javascript

I have a table that needs edit buttons in each row, on click the plain text should become input, I've read many tutorial but i understand none as i am new to javascript, can anyone help?
this is what i started with:
<script type="text/javascript">
function Edit(clickedButton){
//get row of the clicked button
var row = clickedButton.closest('tr');
'retrieve each info
var tdID = row.cells[0];
var tdFirstName = row.cells[1];
var tdLastName = row.cells[2];
var tdDOB = row.cells[3];
var tdGender = row.cells[4];
var tdStatud = row.cells[5];
</script>
and this in my table:
<table id="table" class="table .table-bordered" style="width:80%">
<thead>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
<th>DOB</th>
<th>Gender</th>
<th>Martial Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr id="frow">
<td>1</td>
<td>Samir</td>
<td>Khattar</td>
<td>1-12-1990</td>
<td>Male</td>
<td>Married</td>
<td>
<button onclick="Edit(this)">Edit</button>
<button onclick="Delete(this)">Delete</button>
</td>
</tr>
</tbody>
</table>
and whats the difference between .innerhtml and .html
At first take a form to get input as you want. Then hide the input area as default. And show As you are showing your table inside the form. If any of the button is clicked then the hidden input area will be shown and the the default table row will be hidden. This is the idea to do so.
innserHTML is a javascript DOM property. It return DOM's inner html, it can also be used as to change the inner html of that dom. On the other hand, html() is a jQuery library function to do the same work. May be this method of jQuery actually use the innserHTML property.
To know about the performance of innerHTML and & html() you can check out this link: .append VS .html VS .innerHTML performance
Best of luck
Simply do like this...it will work...
$(function () {
$("#table td").click(function (e) {
e.preventDefault(); // <-- consume event
e.stopImmediatePropagation();
$this = $(this);
if ($this.data('editing')) return;
var val = $this.text();
$this.empty()
$this.data('editing', true);
$('<input type="text" class="editfield">').val(val).appendTo($this);
});
putOldValueBack = function () {
$("#table .editfield").each(function(){
$this = $(this);
var val = $this.val();
var td = $this.closest('td');
td.empty().html(val).data('editing', false);
});
}
$(document).click(function (e) {
putOldValueBack();
});
});
//Refer this example
<table id="table">
<tr>
<th>RecID</th>
<th>Col1</th>
<th>Col2</th>
</tr>
<tr>
<td>RecID</td>
<td>Val1.1</td>
<td>Val1.2</td>
</tr>
<tr>
<td>RecID</td>
<td>Val2.1</td>
<td>Val2.2</td>
</tr>
<tr>
<td>RecID</td>
<td>Val3.1</td>
<td>Val3.2</td>
</tr>
</table>
Try this
function Edit(clickedButton){
var getTR = clickedButton.parentNode.parentNode;
var getLength = getTR.childElementCount;
var getTds = getTR.querySelectorAll("td")
for (i in getTds){
if(i < (getLength-1)){
getTds[i].innerHTML = "<input type='text' value='"+getTds[i].innerHTML+"'>";
}
}
}

jQuery: skipping first table row

This is the HTML:
<table id="tblTestAttributes">
<thead>
<tr> <th>Head 1</th> <th>Head 2</th> </tr>
</thead>
<tbody>
<tr> <td id="txtDesc">Item 1</td> <td id="ddlFreq">Assume a DropDownList Here</td> </tr>
<tr> <td id="txtDesc">Item 1</td> <td id="ddlFreq">Assume a DropDownList Here</td> </tr>
<tr> <td id="txtDesc">Item 1</td> <td id="ddlFreq">Assume a DropDownList Here</td> </tr>
</tbody>
</table>
This is the javascript to get the values of each row:
var frequencies = [];
if ($('#tblTestAttributes').length) {
$('#tblTestAttributes tr').each(function () {
var t = $(this).find('td[id^="txtDesc"]').text() + ";" + $(this).find('[id^="ddlFreq"] option:selected').val();
alert(t);
frequencies.push(t);
});
}
I want to avoid the first row, which contains th elements which are just display headers and don't contain any data.
So I changed the selector to this:
#tblTestAttributes tr:not(:first-child)
This is skipping the second tr as well. What is happening here?
Simple you can use below code
$('#tblTestAttributes tr:not(:has(th))').each(function () {
In terms of performance, using .find() will be better than resolving the selector with Sizzle.
$('#tblTestAttributes').find('tbody').find('tr').each(function () { ... });
Here's the jsPerf to show it.
use
#tblTestAttributes tr:gt(0)
or
#tblTestAttributes tbody tr
I would recommend the 2nd, because it may take advantage of querySelectorAll and should be the fastes solution.
your approach didn't work as expected, because the 2nd tr is also a first-child(of tbody)
Use tr + tr selector, which gets all tr that appear after another tr, so the first one is skipped.
Also no need to check if table exists, as in that case $.each wouldn't even get executed.
var frequencies = [];
$('#tblTestAttributes tr + tr').each(function () {
var t = $(this).find('td[id^="txtDesc"]').text() + ";" + $(this).find('[id^="ddlFreq"] option:selected').val();
alert(t);
frequencies.push(t);
});
After your edit:
Simply select only all tr inside tbody:
$('#tblTestAttributes tbody tr').each(function(){
...
}
It happens because the second row is, in fact, the first child of the tbody just like the first row is the first child of the thead.
To only take the elements you need, I'd suggest something nearer from your need :
#tblTestAttributes tr:has(td)
Don't forget to get rid of those duplicate txtDesc id, this is illegal in HTML, use a class instead.

How to tell which row number is clicked in a table?

I have a table like the following:
<table>
<tr>
<td>1</td><td>1</td><td>1</td>
</tr>
<tr>
<td>2</td><td>2</td><td>2</td>
</tr>
<tr>
<td>3</td><td>3</td><td>3</td>
</tr>
</table>
When a user clicks on the table, how can I get the index of this row (tr element)?
For example, when I click on the first tr (with 1s in the above table), it should pick it up and return 1.
This would get you the index of the clicked row, starting with one:
$('#thetable').find('tr').click( function(){
alert('You clicked row '+ ($(this).index()+1) );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="thetable">
<tr>
<td>1</td><td>1</td><td>1</td>
</tr>
<tr>
<td>2</td><td>2</td><td>2</td>
</tr>
<tr>
<td>3</td><td>3</td><td>3</td>
</tr>
</table>
If you want to return the number stored in that first cell of each row:
$('#thetable').find('tr').click( function(){
var row = $(this).find('td:first').text();
alert('You clicked ' + row);
});
A better approach would be to delegate the event, which means catching it as it bubbles to the parent node.
delegation - overview
This solution is both more robust and efficient.
It allows the event to be handled even if more rows are dynamically added to the table later, and also results in attaching a single event handler to the parent node (table element), instead of one for each child node (tr element).
Assuming that the OP's example is a simplified one, the table's structure can be more complex, for example:
<table id="indexedTable">
...
<tr>
<td><p>1</p></td>
<td>2</td>
<td><p>3</p></td>
</tr>
</table>
Therefore, a simplistic approach such as getting e.target.parentElement will not work, as clicking the internal <p> and clicking the center <td> will produce different results.
Using delegation normalizes the event handling, only assuming that there are no nested tables.
implementation
Both of the following snippets are equivalent:
$("#indexedTable").delegate("tr", "click", function(e) {
console.log($(e.currentTarget).index() + 1);
});
$("#indexedTable").on("click", "tr", function(e) {
console.log($(e.currentTarget).index() + 1);
});
They attach a listener to table element and handle any event that bubbles from the table rows. The current API is the on method and the delegate method is legacy API (and actually calls on behind the scenes).
Note that the order of parameters to both functions is different.
example
A comparison between direct handler attachment and delegation is available below or on jsFiddle:
$("#table-delegate").on("click", "tr", function(e) {
var idx = $(e.currentTarget).index() + 1;
$("#delegation-idx").text(idx);
console.log('delegated', idx);
});
$("#table-direct tr").on("click", function(e) {
var idx = $(e.currentTarget).index() + 1;
$("#direct-idx").text(idx);
console.log('direct', idx);
});
$('[data-action=add-row]').click(function(e) {
var id = e.target.dataset.table;
$('#' + id + ' tbody')
.append($('<tr><td>extra</td><td>extra</td><td>extra</td></tr>')[0])
});
tr:hover{
background:#ddd;
}
button.add-row {
margin-bottom: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<h1>Event handling test</h1>
<p>Add rows to both tables and see the difference in handling.</p>
<p>Event delegation attaches a single event listener and events related to newly added children are caught.</p>
<p>Direct event handling attaches an event handler to each child, where children added after the inital handler attachment don't have a handler attached to them, and therefore their indices won't be logged to console.</p>
<h2>Delegation</h2>
<p><span>row index: </span><span id="delegation-idx">unknown</span></p>
<button class="add-row" data-action="add-row" data-table="table-delegate">Add row to delegation</button>
<table id="table-delegate" class="table">
<tbody>
<tr>
<td>normal</td>
<td>normal</td>
<td>normal</td>
</tr>
<tr>
<td><p>nested</p></td>
<td><p>nested</p></td>
<td><p>nested</p></td>
</tr>
<tr>
<td>normal</td>
<td>normal</td>
<td><p>nested</p></td>
</tr>
</table>
<h2>Direct attachment</h2>
<p><span>row index: </span><span id="direct-idx">unknown</span></p>
<button class="add-row" data-action="add-row" data-table="table-direct">Add row to direct</button>
<table id="table-direct" class="table">
<tbody>
<tr>
<td>normal</td>
<td>normal</td>
<td>normal</td>
</tr>
<tr>
<td><p>nested</p></td>
<td><p>nested</p></td>
<td><p>nested</p></td>
</tr>
<tr>
<td>normal</td>
<td>normal</td>
<td><p>nested</p></td>
</tr>
</tbody>
</table>
Here's the demo on jsFiddle.
P.S:
If you do have nested tables (or, in the general case, wish to delegate to elements with specific depth), you can use this suggestion from the jQuery bug report.
A simple and jQuery free solution:
document.querySelector('#elitable').onclick = function(ev) {
// ev.target <== td element
// ev.target.parentElement <== tr
var index = ev.target.parentElement.rowIndex;
}
Bonus: It works even if the rows are added/removed dynamically
You can use object.rowIndex property which has an index starting at 0.
$("table tr").click(function(){
alert (this.rowIndex);
});
See a working demo
$('tr').click(function(){
alert( $('tr').index(this) );
});
For first tr, it alerts 0. If you want to alert 1, you can add 1 to index.
In some cases we could have a couple of tables, and then we need to detect click just for particular table. My solution is this:
<table id="elitable" border="1" cellspacing="0" width="100%">
<tr>
<td>100</td><td>AAA</td><td>aaa</td>
</tr>
<tr>
<td>200</td><td>BBB</td><td>bbb</td>
</tr>
<tr>
<td>300</td><td>CCC</td><td>ccc</td>
</tr>
</table>
<script>
$(function(){
$("#elitable tr").click(function(){
alert (this.rowIndex);
});
});
</script>
DEMO

Categories

Resources