jQuery cloning of table row breaks button - javascript

I have a html table (Bootstrap 3) which has a button in its last td of each row. This button has a class btn-add-row. In my Javascript I use (from this question):
$('.btn-add-row').click(function() {
var $tr = $(this).closest('tr');
var $clone = $tr.clone();
$clone.find('input').val('');
$tr.after($clone);
});
Now, the row which is cloned also contains that specific button. It copies the button without issue, but when you click the button in the row which was added, the javascript is not executed. The copied button does have the class btn-add-row, and clicking buttons which were originally already on the page still work.
How can I fix this issue?

You have to options here.
First to add click handler for cloned row
function clickHandler() {
var $tr = $(this).closest('tr');
var $clone = $tr.clone();
$clone.find('.btn-add-row').click(clickHandler);
$clone.find('input').val('');
$tr.after($clone);
}
$('.btn-add-row').click(clickHandler);
And the other to use event delegation
$( "table" ).on( "click", ".btn-add-row", clickHandler);

Related

How to catch td index in Datatable?

I have datatable and trying to catch column+row index when user press on it:
$('#datatable tbody').on('click', 'tr', function(){
var eq = $(this).index();
console.log(eq);
});
So, I could catch index of row (tr) by this way. However, I need also column (td index) with it. Does anyone could advise some approach?
Here is an example of similar task, just from backside (when someone needs few catchers). I am not good enought in jquery to convert it to my trouble.
You can listen for td clicks and then get the indices of both the clicked td and it's parent tr:
$('#datatable tbody').on('click', 'td', function(){
var clicked_td = $(this);
var td_index = clicked_td.index();
var tr_index = clicked_td.parent().index();
console.log(td_index);
console.log(tr_index);
});

Dynamic Modal Bootstrap

I have a table like:
When user selects Edit, it opens up a bootstrap Modal containing all td of the tr the Modal is launched from. What I've done so far is:
Get Row Index on Edit Click:
$(document).on('click', '#editNominHref', function(e) {
var global_edit_row = $(this).closest('tr').index();
$('#editNomiModal').modal('show');
});
What I want is:
$('#editNomiModal').on('show.bs.modal', function () {
$("#Name_feild_of_Modal").val(name_in_td_of_nth_Tr);
// ..Similar for DOB, Relation and share%..
});
Question:
How do I pass the tr index from Edit.click to Modal.show function?
I don't believe you can pass data directly to the modal. However, you can use data attributes to modify the DOM which can then be read from the show.bs.modal event. Something like this:
$(document).on('click', '#editNominHref', function(e) {
$('#editNomiModal')
.data('row-index', $(this).closest('tr').index())
.modal('show');
});
$('#editNomiModal').on('show.bs.modal', function () {
var $tr = $('#myTable tr').eq($(this).data('row-index'));
var serial = $tr.find('td:eq(0)').text();
var name = $tr.find('td:eq(1)').text();
// and so on...
$("#Serial_field_of_Modal").val(serial);
$("#Name_field_of_Modal").val(name);
// and so on...
});
When you open the modal can't you just clone the <tr> and insert into modal-content?
$(document).on('click', '#editNominHref', function(e) {
var content = $(this).closest('tr').html();
$('#editNomiModal').find('modal-content').html(content).modal('show');
});
Obviously more formatting would be required.

Appending an element to a cloned element

I have a form with an HTML table that has a button (#addRows) that when clicked will clone the first table row and append it to the bottom of the table.
This table resides in a section of HTML with some other input fields that can also be cloned and appended onto the bottom of my form. When I am cloning the section I am changing all child element ID's to include a number that can be iterated dependent on how many times the user clones the section.
Example
<div id="someID"> ... </div>
<div id="someID2"> ... </div>
<div id="someID3"> ... </div>
I am doing this with JQuery like this
$(function() {
var $section = $("#facility_section_info").clone();
var $cloneID = 1;
$( ".addSection" ).click(function() {
var $sectionClone = $section.clone(true).find("*[id]").andSelf().each(function() { $(this).attr("id", $(this).attr("id") + $cloneID); });
$('#facility_section_info').append($sectionClone);
$cloneID++;
});
});
When I clone the section that holds the table I am also cloning the #addRows button which when clicked should append a table row to the table it is being clicked on. However if I clone my section and I click on my second `#addRows button it will clone my table row but it is appending to my first table and not the second.
Here is my addRows button and event handler
<input type="button" value="+" id="addRows" class="addRows"/>
$(function() {
var $componentTB = $("#component_tb"),
$firstTRCopy = $("#row0").clone();
$idVal = 1;
$(document).on('click', '.addRows', function(){
var copy = $firstTRCopy.clone(true);
var newId = 'row' +$idVal;
copy.attr('id', newId);
$idVal += 1;
copy.children('td').last().append("Remove");
$componentTB.append(copy);
});
});
My question is, when I clone my section of HTML that holds my table and #addButton how can I ensure that when the user clicks on the original button it will clone and append to that table or if I click the cloned button it will clone and append to the cloned table only?
If anything is unclear please let me know so I can try to better explain what I am trying to do, thanks.
Here is a JSFiddle demonstrating the problem I am having.
Because I truly love you BigRabbit, here is where I got to. You will see at least one useful fix here:
var $sectionClone = $section.clone(true);
$sectionClone.find("*[id]").andSelf().each(function () {
$(this).attr("id", $(this).attr("id") + $cloneID);
});
and a fix for an issue you did not report yet
$copy.children('td').last().append(' Remove');
using
$("#facility_section_info").on('click', '.remove', function (e) {
e.preventDefault();
$("#"+$(this).data("removeid")).remove();
});
FIDDLE
$(function () {
var $componentTB = $("#component_tb"),
$firstTRCopy = $("#row0").clone(),
$section = $("#facility_section_info>fieldset").clone(),
$cloneID = 0,
$idVal = 0;
$("#facility_section_info").on('click', '.remove', function (e) {
e.preventDefault();
$("#"+$(this).data("removeid")).remove();
});
$("#facility_section_info").on('click', '.addRows', function () {
$idVal++;
var $copy = $firstTRCopy.clone(true);
var newId = 'row' + $idVal;
$copy.attr('id', newId);
$copy.children('td').last().append(' Remove');
$(this).closest("fieldset").find("tbody").append($copy);
});
$("#facility_section_info").on("click", ".addSection", function () {
$cloneID++;
var $sectionClone = $section.clone(true);
$sectionClone.find("*[id]").andSelf().each(function () {
$(this).attr("id", $(this).attr("id") + $cloneID);
});
$('#facility_section_info').append($sectionClone);
});
});

Getting the td that was clicked when a tr was clicked

Lets say I have a click event set up for all TRs, naturally each TR is filled with TDs, so when you click a TR you are also clicking a TD. Is there anyway to capture the TD (or its index) that was clicked as a result of a TR being clicked?
I thought perhaps something like this, but I'm not getting anything out of that.
$('tbody').on('click', 'tr', function(){
var thisEq = $(this+' td').index();
alert("thisEq: "+thisEq);
});
Demo
You can get the td using event.target
$('tbody').on('click', 'tr', function(e){
var thisEq = $(e.target).index();
alert("thisEq: "+thisEq);
});
Note : .index() gives 0 to n values, so you would get 0 for first td
Reverse the problem round - detect which td is clicked and detect the parent tr.
$('td').on('click', function(){
var tr = $(this).parent('tr');
alert(tr);
});
You could also do this through use of a delegated event handler. This one hooks onto each tr element but you could hook it onto the body as another submitter has just proposed
$('tr').on( 'click', 'td', function() {
...
});

JavaScript generated elements not functioning - jQuery

I have a table as below;
<table id="mytable">
<tr>
<td>cola1</td>
<td>cola2</td>
<td>cola3</td>
<td class="rem">cola4</td>
</tr>
<tr>
<td>colb1</td>
<td>colb2</td>
<td>colb3</td>
<td class="rem">colb4</td>
</tr>
</table>
<button id="but">Add Row</button>
A button <button id="but">mybutton</button> is placed at bottom of table, which on click, adds a new row to the table. The last column of rows have class rem, which has a function to remove the parent row on click.
Here is the javascript
$(document).ready(function() {
$('#but').click(function() {
row = $("<tr></tr>");
col1 = $('<td>colex1</td>');
col2 = $('<td>colex2</td>');
col3 = $('<td>colex3</td>');
col4 = $('<td class="rem">colex4</td>');
row.append(col1,col2,col3,col4).prependTo("#mytable");
});
$('.rem').click(function() {
var $button = $(this);
var $row = $button.closest('tr');
$row.fadeOut('slow');
});
});
The function work well in above two rows. But remove button is not working in rows added by jQuery. How can I make the Javascript added rows work like others?
Here is the fiddle.
You need to use a delegated event handler, using on(), if you want it to apply to newly created elements. The way this works is by adding the handler to an element that already (and continues) to exist in the DOM, then in the handler, as the event bubbles up, it checks whether the event target matches the selector supplied to the on() function. If so, then it runs the handler otherwise it doesn't.
$('#mytable').on('click','.rem',function() {
var $button = $(this);
var $row = $button.closest('tr');
$row.fadeOut('slow');
});
I think a lot of it comes down to how you handle the functionality. You could use $.on() or some other listener, but I don't think it's necessary if you know when you're adding the element and it's entirely under your control.
For instance:
EDIT - Fixed having the click handler on the row, put it on the .rem element instead.
$(document).ready(function() {
var $row = $("<tr>"),
$col1 = $('<td>colex1</td>'),
$col2 = $('<td>colex2</td>'),
$col3 = $('<td>colex3</td>'),
$col4 = $('<td class="rem">colex4</td>');
var addrow = function() {
$row.clone(true).prependTo("#mytable");
};
var removerow = function() {
var $button = $(this),
$row = $button.closest('tr');
$row.fadeOut('slow');
};
$row.append($col1, $col2, $col3, $col4);
// This could be $($col4).click(removerow);, too.
$row.find('.rem').click(removerow);
$('#but').click(addrow);
$('.rem').click(removerow);
});
http://jsfiddle.net/sM2R8/4/
Now this uses caching of the new $row with a $.clone(true) to copy the click handlers that have been added. If you want to change the values, you'll need to clone and then update those values, but that's just a nuance to how you want to handle this. You could, also, just add the removerow handler to the cloned element before/after you append it to the table, too.
Try this:
$('#mytable').on('click', '.rem', function() {
var $button =$(this);
// ...
});
By doing that, you establish a handler on the table itself that listens for events bubbling up from contained elements. The second argument is a selector against which the actual target element is tested. If it matches (in this case, if it's a "remove" button), then your handler function is called.
Thus you can add as many rows as you like, and each new button's events will be intercepted by the same handler.
Your click handler works on existing rows only because they do exist when you call it. For future elements not in the DOM though you need to use a delegation method that accounts for both current and future elements. To do this use on() delegated to the table ( or element further up that will always exist) and add the button class as selector
$('#mytable').on('click','.rem',function() {
var $button = $(this);
var $row = $button.closest('tr');
$row.fadeOut('slow');
});
You can use
.live(event, handler)
In this case event handler will be attached to the future elements also.
so use:
$('.rem').live('click', function() {
var $button = $(this);
var $row = $button.closest('tr');
$row.fadeOut('slow');
});
However as of jQuery 1.7 live() is deprecated, use on()

Categories

Resources