This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 5 years ago.
I am trying to get the value of table row using jQuery. When I try the same jQuery code on console and after I try to click, that is selecting that row and give proper value what I expect. But I don't know why it is not running from my JavaScript file. But the other functions are working on the same JavaScript file
$(".chequeTable tbody tr").click(function() {
alert('Vendor ID ==');
$('.selected').removeClass('selected');
$(this).addClass("selected");
alert('Vendor ID ==' + $('.tdVendorID').html());
$(this).css("background-color", "#000000");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table table-hover FilterTable chequeTable table-striped" id="queryTable">
<thead>
<tr>
<th>S.No</th>
<th>VendorID</th>
<th>VendorName</th>
<th>ReqNo</th>
<th>ChequeAmount</th>
<th>VendorBalance</th>
<th>Balance</th>
<th>Description</th>
<th>StockValue</th>
<th>Yes/No</th>
</tr>
</thead>
<tbody>
<tr class="">
<td class="tdSno">1</td>
<td class="tdVendorID">6000 </td>
<td class="tdVendorName">john</td>
</tr>
</tbody>
</table>
Most probably the table is not there when you initialize the click event in jquery. Do you build the table dynamically?
Try to bind the click event to the table instead of the tr directly:
$(".chequeTable").on("click", "tr", function() { ... });
This only works when the table.chequeTable is in the HTML.
Some explanation why:
jquery documentation for on()
It says that it binds the events to all the elements in the selector. That means, elements that are not in the selector (any tr that is not yet present for example) won't receive the event. For that you have to bind the click Event on a container and check what the clicked subelement is. This is more perfomant anyways because you only attach one click Event and not 100s (if you have 100s tr-Elements)
Here you go with a solution
$("table.chequeTable").on('click', 'tr', function() {
alert('Vendor ID ==');
$('.selected').removeClass('selected');
$(this).addClass("selected");
alert('Vendor ID ==' + $('.tdVendorID').html());
$(this).css("background-color", "#000000");
});
$('tbody').append(`<tr class="">
<td class="tdSno">1</td>
<td class="tdVendorID">6000 </td>
<td class="tdVendorName">john</td>
</tr>`);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="table table-hover FilterTable chequeTable table-striped" id="queryTable">
<thead>
<tr>
<th>S.No</th>
<th>VendorID</th>
<th>VendorName</th>
<th>ReqNo</th>
<th>ChequeAmount</th>
<th>VendorBalance</th>
<th>Balance</th>
<th>Description</th>
<th>StockValue</th>
<th>Yes/No</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
You need to do event delegation as your row are generated dynamically.
Reference Documentation: Event delegation
Hope this will help you.
Related
I have a htmltable that is dynamically created. I have made the rows clickable.
I need to pass the row innertext id to the script that fires when the row is clicked.
htmltable:
<table style="width:100%;">
<tr>
<th>id</th>
<th>name</th>
<th>other info</th>
</tr>
<tr>
<td class='table_row_click'>11</td>
<td class='table_row_click'>item 2</td>
<td class='table_row_click'>lmfao</td>
</tr>
<tr>
<td class='table_row_click'>22</td>
<td class='table_row_click'>item 2</td>
<td class='table_row_click'>lol</td>
</tr>
</table>
Click event:
$(document).ready(function ($) {
$(".table_row_click").click(function (e) {
//I need to use the clicked row ID here for something
});
});
$(e.target).closest('tr').find('td').first().text();
You can navigate up to the parent tr, find the td elemements, get the first one, and get its text.
Using closest('tr') will work if the class is on the td or tr level, as closest() can match on itself.
I have written a code where i need to trigger a functionality when mouse is over to specific elements.
Its working fine for below code for all static
$("table td").on("mouseenter",function(){
console.log("mouse entered")
});
but for all dynamic <td class="editcolumn">XYZ</td> event is not triggering even if i use below code
$("table td").on("mouseenter",".editcolumn",function(){
console.log("mouse entered")
});
Any idea how to make it work. I'm using jQuery 1.11
I know I just commented, but I figured I would show you an example:
HTML:
<table id="tablee" cellspacing="0">
<thead>
<tr class="tablehead">
<th>This</th>
<th>is</th>
<th>a</th>
<th>table</th>
<th>header</th>
<th>and</th>
<th>stuff</th>
<th>though</th>
</tr>
</thead>
<tr class="append">
<td class="edit-column">asdf</td>
<td class="edit-column">qwer</td>
<td class="edit-column">zxcv</td>
<td class="edit-column">rtyu</td>
<td class="edit-column">tyui</td>
<td class="edit-column">dfgh</td>
<td class="edit-column">dfgh</td>
<td class="edit-column">wert</td>
</tr>
<!-- ... -->
</table>
<br/>
<br/>
<input type="button" class="add-column" value="Add Column" />
Javascript:
$(function() {
$('.add-column').click(function() {
$('.append').append("<td class='edit-column'>iueo</td>");
$('.tablehead').append("<th>Mo columns</th>");
});
/* vvv - this */
$("#tablee").on('mouseenter', '.edit-column', function() {
/* ^^^ should be children or a child of this */
$(this).css('background-color', 'yellow');
});
});
Here is a fiddle
This question's answer gives a much better explanation of delegated events.
I too faced a similar problem for dynamic elements that are added or removed. In such situations you can create dynamic elements with event-handlers attached to their attributes i.e. in your case you can put the desired operations in a function which gets called by your attribute event handlers:
It should be something like this:
Javascript:
function whenMouseEnters() {
// perform some operations
}
Html:
<td onmouseenter="whenMouseEnters()">
If table is aviable on DOM load you can write delgated event for the td with class editColumn like this:
$("table").on("mouseenter",".editcolumn",function(){
console.log("mouse entered")
});
I have this HTML:
<table class="itemsTable table table-striped table-condensed table-hover">
<thead>
<tr>
<th>#</th>
<th>Location</th>
</tr>
</thead>
<tbody>
<tr class="collapse">
<td class="center">1</td>
<td>
Title 1
</td>
</tr>
<tr class="collapse">
<td class="center">2</td>
<td>
Title 2
</td>
</tr>
<tr class="collapse">
<td class="center">3</td>
<td>
Title 3
</td>
</tr>
</tbody>
</table>
test
And jQuery:
$('.collapseBtn').on('click', function(e) {
e.preventDefault();
var $this = $(this);
var $collapse = $this.closest('.itemsTable').find('.collapse');
$collapse.collapse('toggle');
});
I want rows show/hide behavior on link click. What is wrong?
$.closest will look up the dom tree for a matching element - the .itemsTable isn't a parent of .collapseBtn - so $this.closest('.itemsTable') won't match any elements.
So, Either put the .collapseBtn within the table, or use $this.prev() instead of $this.closest('.itemsTable').
You can test if there are matching elements by running $('.collapseBtn').closest('.itemsTable') in the console
As of 130918_1100PST the selected answer is not correct. Although the writer did correctly identify why the closest() selector would not return any elements to collapse, this alone did not fix the OP's problem.
This selector will also work for selecting the elements to collapse:
$('.collapse').methodgoeshere();
but the elements won't expand/collapse -- it's not just a matter of the selector used.
The key to solving the problem, as user Chad identified in his jsFiddle below benjaminbenben's answer, is actually that the wrong method was used.
This did not work:
selector.collapse('toggle');
This did:
selector.toggle();
Therefore, the correct answer was:
$('.collapseBtn').on('click', function() {
$('.collapse').toggle();
});
jsFiddle here
I have a question, I am trying to make some manipulation with html tables. I have two tables,
and when I hover first row from the first table, it should highlight both rows from both tables.
I have found a solution, in making this simple function:
<script type="text/javascript">
function matchrow(){
document.getElementById('row1').style.backgroundColor='#f5f5f5';
}
function unmatchrow(){
document.getElementById('row1').style.backgroundColor='white';
}
</script>
On the first table I have:
<tr onmouseover="matchrow()" onmouseout="dismatchrow()" >
on the second table I have:
<tr id="row1" >
So when I put mouseover the first row from the first table, the first row from the second table highlights.
My question is, how to make it for the every single row, especially if it will be dynamic table.
Hope I was clear.
I've implemented this with jQuery. It doesn't use obtrusive JS and doesn't require additional IDs for rows.
Also, CSS classes are more preferable than inline styles.
HTML:
<table id="t1">
<tr><td>......</td></tr>
<tr><td>......</td></tr>
</table>
<br/>
<table id="t2">
<tr><td>......</td></tr>
<tr><td>......</td></tr>
</table>
CSS:
tr.active > td
{
background-color:#f00;
}
JS:
$(function(){
$("#t1 tr").hover(
function(){
$(this).addClass('active');
$('#t2 tr:eq(' + $('#t1 tr').index($(this)) + ')').addClass('active');
},
function(){
$(this).removeClass('active');
$('#t2 tr:eq(' + $('#t1 tr').index($(this)) + ')').removeClass('active');
}
);
});
Here is live fiddle: http://jsfiddle.net/keaukraine/KBEhA/1/
You can use the div id as a parameter in the function
<tr onmouseover="matchrow('row1')" onmouseout="dismatchrow('row1')">
function matchrow(divid){
document.getElementById(divid).style.backgroundcolor='#F5F5F5';
}
function dismatchrow(divid){
document.getElementById(divid).style.backgroundcolor='white';
}
You can use jQuery for this.
Use the .eq() and .index() functions.
A way of doing it:
HTML:
<table border="1">
<tr>
<td>Row1</td>
</tr>
<tr>
<td>Row2</td>
</tr>
<tr>
<td>Row3</td>
</tr>
<tr>
<td>Row4</td>
</tr>
</table>
<table border="1">
<tr>
<td>Row1</td>
</tr>
<tr>
<td>Row2</td>
</tr>
<tr>
<td>Row3</td>
</tr>
</table>
JS:
$('table tr').hover(function()
{
var index = $(this).index();
$('table').each(function()
{
$(this).find('tr').eq(index).css('color', 'red');
});
});
A working example can be found here.
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