JavaScript doesn't work after ajax loading (using table) - javascript

i have a table automatically generated by database using php with four rows ... the last row (4) has a button to trigger the function below... it repeats for every line.
after i click the button...the script sends a request to update database to switch the status "pendent" to "canceled".
at this point everything is okay... BUT...when i refresh the div with the table"$( '#lista' ).load(location.href + ' #lista > *' );"
the script doesnt work a second time after the loading. ( the div update is okay but only works a once)
i need the script working after the first refresh... everytime i clicked in the row button...
i think that may be a incompatibility of ajax request and javascript.
i really appreciate if you can help me.
thank you all.
<script>
var index, table = document.getElementById('table');
for(var i = 1; i < table.rows.length; i++)
{
table.rows[i].cells[4].onclick = function()
{ //inicio da função
var c = confirm('Você quer cancelar essa aula?');
if(c === true)
{//inicio confirmador
var table = document.getElementById('table');
index = this.parentElement.rowIndex;
value_index_id= table.rows[index].cells[0].innerHTML;
var id = value_index_id;
$.ajax({
type: 'GET',
url: 'cancelar_aulas.php',
data: {id_geral:id},
success: function(data){
alert(data);
$( '#lista' ).load(location.href + ' #lista > *' );
}
})
} //fim do confirmador
//validador
//console.log(index);
//console.log (value_index_id);
console.log(id);
};//fim da função
}
</script>";

You're only attaching the onclick event handler to the table when your page loads. That's why it only works on the first click. When you add new data to the table, you need to do something to add the onclick event to the new rows.
There's a few different ways to do this:
jQuery can attach events to dynamically created elements like so:
$("table").on("click", "table tr", function() {
// Note that this event would fire for ALL rows,
// but it will automatically attach this event to new rows
// that are added after page load
// This would work, you just would have to check if the clicked
// row is one of the last 4.
}
Create your own function to attach the event, and you'll run that function every time you add new rows. Something like:
function AttachClick() {
let table = document.getElementById("table");
let position = table.rows.length;
while (position > table.rows.length - 4) {
table.rows[position].addEventListener("click", function() {
// Do your on click here
// On success, you would fire this "AttachClick()" function
}
position--;
}
}
Notice the while loop starting from the end of the table instead of the start. If you had a table with a lot of rows it could be faster to iterate starting at the end (since those are the only rows you care about).

Related

jquery function not firing when I use datatable.fnAddData to append the HTML string

jquery function not firing when I use dataTable.fnAddData to append the HTML string.
So I have a function populateDataTable(), there are two columns I needed to render an icon instead of data from JSON.
Hence, I tried to like appending the HTML string including classes for the element in fnAddData(). But somehow it's not firing the click event on the icon.
function populateDataTable(data) {
$("#customerTable").DataTable().clear();
var length = Object.keys(data).length;
for(var i = 1; i < length+1; i++) {
var index = i - 1;
var name = data[index].name;
var queue = data[index].queue;
var expire = data[index].expire;
$('#customerTable').dataTable().fnAddData( [
i,
name,
queue,
'<td id="tb-manage-key" class="tb-manage-key"><div class="tb-btn manage-key-btn switch-view" data-hide="manageCustomers" data-title="#Resources.ManageKeys" data-target="manageKeys"><span></span></div></td>',
'<td class="tb-manage-subs"><div class="tb-btn manage-subs-btn switch-view" data-hide="manageCustomers" data-title="#Resources.ManageSubscriptions" data-target="manageSubscriptions"><span></span></div></td>',
expire,
name
]);
}}
$('.tb-btn.switch-view').on('click', function(e) {
e.preventDefault();
switchView(this);
console.log('Testing'); //not firing
});
Icon is showing, but not firing click event as it supposed to be. Attached below shows that we can see it appends the div as expected.
Solutions
Adding the click event within the populateDataTable() works.
$('#customerTable tbody').on('click', '.tb-btn.switch-view', function() {
switchView(this);
});
You can try a different syntax to listen to the click event...
$('td').on('click', '.tb-btn.switch-view', function(e) {
e.preventDefault();
switchView(this);
console.log('Testing'); //not firing
});

on.click not working after first click on dynamically created table

I dynamically create a table full of links of 'actors', which allows to pull the actors information into a form to delete or update the row. The delete button only pops up when you select an actor.
I'm able to click a row, pull the information into the forms, and delete it on first try. However when I attempt to add a new 'Actor' and then delete it, or just delete an existing 2nd row, the button 'Delete Actor' doesn't work. It's only after the first successful delete does the button no longer work.
var addActor = function() {
// Creates a table of links for each added actor with an id based from # of actors
$("#actorsTable").append("<tr><td><a href='' onclick='deleteActor(this)' class='update' data-idx='" + actors.length + "'>" + newActor.fName + " " + newActor.lName + "</a></td></tr> ");
$(".update").off("click");
$(".update").on("click", selectActor);
};
var deleteActor = function(e) {
$("#deleteActor").on('click', function(event) {
event.preventDefault();
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
});
};
I'm new to jQuery/javascript, and I'm pretty sure its due to the change in DOM, but I just don't know what to change to make it work.
Here is an Example of it in action
Try
var deleteActor = function(e) {
$("#deleteActor").unbind();
$("#deleteActor").on('click', function(event) {
event.preventDefault();
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
});
};
Here is the link for unbind.
http://api.jquery.com/unbind/
The problem is because you're adding another click handler (in jQuery) within the click handler function run from the onclick attribute. You should use one method or the other, not both. To solve the problem in the simplest way, just remove the jQuery code from the deleteActor() function:
var deleteActor = function(e) {
var row = e.parentNode.parentNode;
row.parentNode.removeChild(row);
clearForm(actorForm);
actorState("new");
};
when you add html dynamically you need to attach the event to the parent static element like so:
$("#actorsTable").on("click","a.update", function() {
$(this).closest("tr").remove();
});

Some questions around clone/copy TR

I have this code for clone/copy a tr element from a modal to a page.
$(function () {
$('#toggleCheckbox').on('click', function () {
var $toggle = $(this).is(':checked');
$("input:checkbox").attr('checked', $toggle);
$('#btnAplicarNorma').prop('disabled', !$toggle);
});
$('#resultadoNormaBody').on('change', 'input[type=checkbox]', function () {
var $my_checkbox = $(this);
var $my_tr = $my_checkbox.closest('tr');
if ($my_checkbox.prop('checked')) {
$my_tr.addClass('copyMe');
}
var $all_checkboxes = $my_checkbox.closest('tbody').find('input[type=checkbox]');
$all_checkboxes.each(function () {
if ($(this).prop('checked')) {
$('#btnAplicarNorma').prop('disabled', false);
return false;
}
$('#btnAplicarNorma').prop('disabled', true);
});
});
$('button#btnAplicarNorma').on('click', function (ev) {
var $tr_to_append = $('#resultadoNormaBody').find('tr.copyMe');
$('#tablaNorma').removeAttr('style');
$('#alertSinNorma').hide();
if ($tr_to_append.length) {
$tr_to_append.find('input[type=checkbox]').prop('checked', false);
$tr_to_append.clone().appendTo('#normaBody').removeClass('copyMe');
$tr_to_append.removeClass('copyMe');
$(this).prop('disabled', true);
}
});
});
But I'm having some issues:
If I mark all checkboxes using the first on the table head then I the code stop working and doesn't clone any tr even if all of them are marked
How do I avoid to clone/copy the same tr twice?
It's possible to modify the checkbox before clone it? If you take a look at the example you'll notice how the clone tr copy exactly as the one on the modal and I want to uncheck the checkbox first, it's possible?
Here is a fiddle to play with, any advice?
The main problem is that your checkboxes inside the table do not really get properly triggered when you programmatically set them selected. To make sure all associated Events get properly triggered you should be triggering a .click() event instead:
$("#resultadoNormaBody").find("input:checkbox").click();
to ensure that you don't end up with duplicate clones the easiest thing is to not clone all the rows in one batch, but iterate thru them, and comparing the html to the ones that have already been added like this:
//fetch all the rows that have already been cloned
var clonedRows = $("#normaBody").find("tr");
//iterate thru all the rows that have been checked
$.each($tr_to_append, function (i, v) {
var added = false;
//fetch their html (for easier compare)
var currentRowHtml = $(v).html();
//now compare against the rows that have already been cloned
$.each(clonedRows, function (i, cRow) {
var clonedRowHtml = $(cRow).html();
if (currentRowHtml == clonedRowHtml) {
added = true;
}
});
//if the row hasn't been added yet- go ahead and clone it now
if (!added) {
$(v).clone().appendTo('#normaBody').removeClass('copyMe');
}
});
Here's a link to your updated fiddle:
http://jsfiddle.net/wq51zL9x/4/
Here is some more info on comparing table rows: Compare two tables rows and remove if match
and here's the more elaborate answer to using .click()
Need checkbox change event to respond to change of checked state done programmatically

Table onclick rows jQuery

I've a table whose content is getting generated via an AJAX success response.
HTML code
<table class="table table-hover" id="table_content"></table>
AJAX code
$.ajax({
dataType: "json",
type : "POST",
url: "/configuration/",
data : { 'selected_item' : selected_item_id },
success : function(result){
var table_heading = "<tr>"
var table_content = ""
for (var heads in result[1]){
table_heading +="<th style='background-color:#f1f1f1;'>" + result[1][heads] + "</th>"
}
for (var region in result[0]){
table_content += "<tr>"
for (var details in result[0][region]){
table_content += "<td>" + result[0][region][details] + "</td>"
}
}
table_content = table_heading + table_content
$("#table_content").html(table_content)
},
});
I want to apply an onclick function to it. Like this:-
Onclick function code
$(function(){
$('#table_content tr').click(function () {
$('.test').slideUp(0)
$(this).append(($('.test')).slideDown('slow'));
});
});
The issue that I'm facing is that I'm not able to click the row, if I generate the content via AJAX response. If I create a table inside the HTML itself, it'll work, but not when the table is created via AJAX response.
What's the problem? Please sugggest.
EDITED
What I'm trying to achieve is that a div should be slide down just below the row upon clicking the row. I does works for the first time when the data gets generated via AJAX. but it does not works when I'm generating data after the first time, though the event is triggered but $('.test').slideUp(0) $(this).append(($('.test')).slideDown('slow')); does not works after the first time. Nor any error is popped . See http://jsfiddle.net/fVz6D/5/
Updated:
See working demo: http://jsfiddle.net/c5FgG/1/
Your problem was that you attached the test div element to a table row, which dissapeared after repopulating the table. Instead, clone the test div on each click when you are changing the table content, and use the clone instead the original.
Old answer:
Add the onclick function code inside the ajax success function. It works out for me this way:
...
$("#table_content").html(table_content);
$('#table_content tr').click(function () {
alert("Clicked");
//your code
});
...
And don't forget to close the table rows with:
table_content += "</tr>";
The way you are using click to bind the event only binds the event to elements that are present in DOM at time the binding code is executed. You need event delegation for binding event with dynamically generated html elements using on().
$(function(){
$('#table_content').on('click', 'tr', function () {
$('.test').slideUp(0)
$(this).append(($('.test')).slideDown('slow'));
});
});
Delegated events
Delegated events have the advantage that they can process events from
descendant elements that are added to the document at a later time. By
picking an element that is guaranteed to be present at the time the
delegated event handler is attached, you can use delegated events to
avoid the need to frequently attach and remove event handlers, reference.
Try
$(function(){
$('#table_content').on('click', 'tr', function () {
$('.test').slideUp(0)
$(this).append(($('.test')).slideDown('slow'));
});
});
The on() handler should work on newly created elements too.
$(function(){
$('#table_content').on('click', 'tr', function () {
$('.test').slideUp(0)
$(this).append(($('.test')).slideDown('slow'));
});
});
Here Is a list of fiddles :
fiddle1
fiddle2
fiddle3
fiddle4
You can use it as per your requirement.
Use on() for dynamically added elements like,
$('#table_content').on('click',' tr', function () {
$('.test').slideUp(0)
$(this).append(($('.test')).slideDown('slow'));
});
Updated your div will move to tr which you clicked, so when you click on list it will generate new content in table so your div.test will be removed from HTML, thats why you are not getting the desc div again.
To solve this problem you have to add div.desc again in clicking of list like,
if(!$('body > div.test').length){
$("body").append('<div class="test">You slide down a row with content xyz</div>');
}
Full code
$('#list').on('click', 'li', function () {
var id = this.id;
var table_content = "";
// IF id=1,2,3,4,5 Code
$("#table_content").html(table_content);
// add below code foe div.desc
if (!$('body > div.test').length) {
$("body").append('<div class="test">You slide down a row with content xyz</div>');
}
});
Demo
Alternatively, you can use clone() like,
$(function () {
$('#table_content').on('click', 'tr', function () {
$clone=$('.test:not(.new-test)').clone();// clone the first test class element
$('.new-test').remove();// remove the cloned elements
$clone.addClass('new-test').appendTo('body');// add the clone to body
$clone.slideUp(0);// playing with clone now
$(this).append($clone.slideDown('slow'));
});
});
Working demo

Javascript (jquery) in my rails app is crashing IE

I've got a ruby on rails app where I'm using a table to display some data, and then allowing the user to edit the data in the table by clicking on the row and popping up a form for the relevant data. When changes are made to the form, the appropriate row in the table is updated.
The event listener for the table row click, which displays the appropriate form, looks like this:
$('.addable-rows > tbody').on('click', 'tr', function(e){
e.preventDefault();
var fieldset = $($(this).data('id'));
if ($(this).hasClass('selected')){
$(this).removeClass('selected');
fieldset.hide('slow');
} else {
$(this).siblings().removeClass('selected');
$(this).addClass('selected');
fieldset.siblings().hide('slow');
fieldset.show('slow');
}
});
The listener that checks for changes in inputs on the form and updates the appropriate row in the table looks like this:
$('.addable_row_host').on('change', ':input', function(){
var fieldset = $(this).closest('fieldset')
var id = fieldset.attr('id')
$('#'+id+'_tr').replaceWith(build_row(fieldset, id));
});
The build row method referenced above is:
function build_row(fields, id){
row = $("<tr id='"+id+"_tr' data-id='#"+id+"' class='selected'></tr>");
fields.find('select, input:not([type=hidden])').each(function(){
val = $(this).val();
if(val == null){
val = '';
}else if(val.indexOf(",") !== -1){
val.split(",").join(", ");
}
row.append('<td>'+val+' </td>');
});
return row;
}
This all works and is quite lovely in Chrome/FF/Safari, but it causes IE to grash most ungracefully. IE pops up a window reporting a crash and reloads the page. No mention of what caused the problem in the console. Additionally, any and all debugging statements in this code runs and is displayed to the console before the crash, so I haven't been able to pinpoint where it's happening.
Anyone know what I'm missing?

Categories

Resources