jQuery Add Dynamic Table with Clickable Rows - php

I'm somewhat new to jQuery, and I see examples of how to add clickable dynamic TRs to existing tables, but how can I add an entirely new table dynamically that has clickable TRs?
My HTML code:
<input type="text" id="containing"><div id="results"></div>
My jQuery code, which POSTs the input and returns the new HTML table into the Results div:
$("#containing").on("keyup", function()
{
$.post("http://URL.com/search.php", { searcher: $(this).val() },function(data, textStatus)
{
$("#results").html(data);
});
});
Search.php returns the following format:
<table id="resultantTable"><tr><td></td></tr></table>
... and additional jQuery code that's supposed to let me click the new table rows, which doesn't work:
$(document).ready(function()
{
$("#resultantTable").on('click','tr',function()
{
var href = $(this).find("a").attr("href");
if(href)
{
window.location = href;
}
});
});
This jQuery code works for tables that load up with the document, but I cannot get the TRs to be clickable in the dynamically-created table that is returned from search.php.
Any ideas?

You need to add the listener on a parent. example:
$(document).on('click', '#resultantTable tr', function(e){
//ToDo...
});

This behaviour happens because you set the event listener on all existing table, but when you dynamically create a table it does not have this listener.
One way to fix this is to set the event listener on the newly created table on creation, but the way I do it is putting the event listener on a parent element which I know exists on document load (like body)
$('body').on({
click: function(){
...
}
}, '#resultantTable tr' )

This happens because the events was registered before the ajax content exist. (resultantTable does not exists the first time the DOM is loaded)
Try to add your function after $("#results").html(data);
it is a good practice, in your ajax call, that you listen on success/error events
Add the render and click jobs inside the success events.
See jquery documentation about that

Related

.on('click') with wildcard not not delegating as expected

Will try to keep this simple so its not too much reading
I have a simple page with the following ...
$divid = 'append_here_$x;
$clickme = 'click_$x';
<div id='$clickme'>Click Me</div>
<div id='$divid'></div>
Then , I have a separate php file that builds content in a while loop generating a unique id for each div.
while ...
$imgid = 'imgid_$z' ...
<div id='$imgid'>This was appended</div>
Finally, I have this just for testing and keeping things short
$( "[id^='imgid_']").on( "click", function() {
alert('you clicked me');
});
This above works fine for the most part. If you were to click on click me, it will do ajax call and a post against the file with the while loop in it, return data and append it inside the append_here_ div. The problem is the new appended data that also has an id so yo can click will not respond to the simple click.
The way you link the click event to the elements of the page will not work for elements added later.
You are linking the event to the elements present by the time you define the click events, but if you add items later, they won't have the event on them. You could do:
$(document).on('click', '[id^="imgid_"]', function() {
alert('you clicked me');
});
That way, the event will be on the document, which is present at the startup, and everytime you click, it will check the selector (second parameter), so the new elements will respond to the click.

How to get checkbox value from ajax loaded content

I have external file which generate the checkbox list. And this file was load through jquery load. I want the checkbox click and update its parent div with something.
html
<div id="testiContent"></div>
checkbox.php
<div class="alert alert-info"><input type='checkbox' class='groupid' value='1'>1</div>
<div class="alert alert-info"><input type='checkbox' class='groupid' value='2'>2</div>
<div class="alert alert-info"><input type='checkbox' class='groupid' value='3'>3</div>
jquery
$('#testiContent').load('checkbox.php');//load file via ajax
$("#testiContent input.groupid").change(function(){
if($(this).is(":checked")){
$(this).parents().addClass("alert alert-success");
}else{
$(this).parent().removeClass("alert alert-success");
}
});
Ideally, when the checkbox click, then the alert div will change into green. I can make it working on the normal scrip but not a chance with ajax.
Fiddle here : http://jsfiddle.net/o6Lk17db/1/
My hunch is that you are simply attaching the change listener before the content is loaded in the DOM, so it doesn't actually target anything. You could pass a callback function to load only attempt to attach the change listener after the content is in the DOM, but it might be easier to just use the on method on the document-- that way it is evergreen and doesn't need to rely on callbacks:
$('#testiContent').load('checkbox.php');//load file via ajax
$(document).on('change', 'input.groupid', function(e){
var target = e.target;
if($(target).is(":checked")){
$(target).parents().addClass("alert alert-success");
}else{
$(target).parent().removeClass("alert alert-success");
}
});
That may not be exactly right but I think it will at least trigger.
You can't bind to an element that isn't there yet, so your dynamically added ones aren't subject to the $"#testiContent input.groupid" selector. The way around this is to bind to something that is already present. For example, the parent container where your elements are dynamically being added.
Try something like this:
$("#testiContent").on('change', 'input', function(){ ... });
will attach a listener to the parent, specifically for events on the appropriate (input) targets within that parent.
When html controls are loaded dynamically, events for these controls needs to be bind manually. So you need to bind check/click events once element adding is done. You can write code as
$(document).on("change","input.groupid").change(function(){
// your code here
});
use this
$("input.groupid").change(function() {
if ($(this).is(":checked")) {
alert($("input.groupid").val());
$(this).closest('div').removeClass("alert-info");
$(this).closest('div').addClass("alert-success");
} else {
$(this).closest('div').removeClass("alert-success");
$(this).closest('div').addClass("alert-info");
}
});
You need to use change event on document because the content is loaded via ajax. and you can use toggleclass function for change the parent div.
$('#testiContent').load('checkbox.php');//load file via ajax
$(document).on('change', '.groupid', function(e) {
$(this).closest("div").toggleClass("alert-success alert-info");
});

jQuery.click on a div that hasn't yet loaded

I dynamically load a div on page Leagues.php with a button like this:
$("#leaguesSelectionTable th").click(function(){
var leagueSelect = $(this).attr('id');
if ($('#leaguesTable').length){
$("#loadLeagueTables").empty();
$("#loadLeagueTables").load("php/leagueTable.php?leagueSelect="+encodeURIComponent(leagueSelect));
}
else {
$("#loadLeagueTables").load("php/leagueTable.php?leagueSelect="+encodeURIComponent(leagueSelect));
}
});
This loads a table based on which button I pressed, using leagueTable.php to handle all of that. Once that table is loaded, (a bunch of leagues) I want to then be able to click on a row from this table and following the same logic, display the team table.
$("#assoc_league tr").click(function(){
var teamSelect = $(this).attr('id');
if ($('#teamsTable').length){
$("#loadTeamTables").empty();
$("#loadTeamTables").load("php/teamTable.php?teamSelect="+encodeURIComponent(teamSelect));
}
else {
$("#loadTeamTables").load("php/teamTable.php?teamSelect="+encodeURIComponent(teamSelect));
}
});
I think the problem is that since table #assoc_league is not yet present, this does not work. I tried an alert and don't get any response. This jQuery is in the same file attached to Leagues.php. Any ideas how to approach this?
Thanks.
Since your table has been added dynamically to the DOM, all the events for this table and child elements inside it will not be avaliable. In this case, you need to use event delegation :
Event delegation allows us to attach a single event listener, to a
parent element, that will fire for all children matching a selector,
whether those children exist now or are added in the future.
$('#loadLeagueTables').on('click', '#assoc_league tr', function() {
// Your code here
});

event handler for clicking a link to ajax call

I'm trying to add a link to delete a row from a mysql database using jquery and ajax. The data is currently displayed in a table. For some reason, the Click event isn't triggering.
Here's my AJAX call:
<script>
$(document).ready(function() {
/* load table with page load*/
$("#sort tbody").load("inc/index_table.php");
/* row deletion */
$(".deletelink").click(function(){
var id = $(this).attr("id");
$.ajax({
beforeSend: function (request) {
var answer = confirm("Are you SURE you want to delete this?/nThis action is NOT reversible.")
if (answer){ return(true); }
else { return(false); }
},
type: "POST",
url: location.href,
data: "delete="+id,
error: function() {
console.log("Theres an error with AJAX deletion");
},
success: function(){ //a.td.tr.remove just that row rather than the whole table
$this.parent().parent().remove();
console.log("Deleted.");
}
});
});
});
</script>
And the relevant HTML:
this is part of a while loop that prints a table from my database:
<td><a class="deletelink" id="'.$row["id"].'"><img src="images/delete.png" alt="Delete"></a></td>';
My code specifies <a class="deletelink"> but it's not registering with $(".deletelink").click(function(){ });
Does anyone see what could be wrong here or have an alternate method to suggest?
Looks like you are loading the elements dynamically. You can only bind to elements which currently exist in the DOM. To bind to elements which you are about to add, you must attach the event to a static element, the closer it is to the dynamic content, the better.
Try using on() with a delegate.
$("#sort tbody").load("inc/index_table.php");
/* row deletion */
$("#sort tbody").on("click", ".deletelink", function(){
//...rest of code the same
});
on() was added in jQuery 1.7. If you are using a previous version, but higher than 1.4.2 you can use delegate() instead.
$("#sort tbody").load("inc/index_table.php");
$("#sort tbody").delegate(".deletelink", "click", function(){
//...rest of code the same
});
If #sort or tbody of $("#sort tbody") is also dynamic then $("document").on("click", "#sort tbody .deletelink", function(){...}) would work as well, though anything closer than document is better off course.
Edit
I'm just looking at your code again, the delegate binding should work, however, using load()'s success callback should work with your existing code too.
The callback is executed ones load has successfully completed. I'm not 100% certain but I'm assuming that when success is called that the elements already have been loaded into the DOM and as such the normal bindings should work.
If that doesn't work the dynamic bindings mentioned above should.
$("#sort tbody").load("inc/index_table.php", function(){
/* row deletion */
$(".deletelink").click(function(){
// .. your code as before.
});
});
to make sure the table is fully loaded, try to declare the click function, in the callback of .load() like,
$("#sort tbody").load("inc/index_table.php", function() {
/* row deletion */
$(".deletelink").click(function(){ ....
});
});
Try using .on() to bind the events to the elements
$(".deletelink").on('click',function(e){
e.preventDefault();
Also make sure to add preventDefault to stop the default functioning of the link
The problem is that your delete link appears after the table loads. So when page was loaded and DOM tree was built, it wasn't there. So you can't attach a click to it.
You can try live(). This can be used as
$(".deletelink").live('click',function(){
// ajax call handling code here
});
This function attaches event after the element has been introduced in the DOM. However, this function is a bit greedy as it keeps on scanning entire DOM tree on any DOM change. So use with caution

Can jQuery be applied in jQuery generated content?

I don't know why this is not working.
When a li element is clicked I call a PHP file to get some results back and print them in my page. So far so good.
$("li").click(function(){
var item = $(this).html();
$.getJSON('fSearch.php',{sTerm: item}, function(data){
var results='';
$.each(data, function(i, item) {
results += "<li id='t'>"+item.Description+"</li>";
});
$('#ResultsHolder').html("<ul>"+results+"</ul>");
});
});
The first time I click to a li element all works fine, I get results. Now these results is another set of li's and I want them to behave the same, but when I click on the generated li's the function is not executed..
Why is this happening? Why jQuery does not recognize the dynamically inserted li elements?
Thanks in advance!
When you use a event shortcut (such as click, or hover) it will only work for events which are available to the DOM on page load. As you are appending elements dynamically you need to delegate the event listener to an element which is always available in your page.
In the example below, I've used #ResultsHolder.
$("#ResultsHolder").on("click", "li", function(){
var item = $(this).html();
$.getJSON('fSearch.php',{sTerm: item}, function(data){
var results='';
$.each(data, function(i, item) {
results += "<li id='t'>"+item.Description+"</li>";
});
$('#ResultsHolder').html("<ul>"+results+"</ul>");
});
});
That should work for jQuery 1.7+. For an older version of jQuery, use delegate()...
$("#ResultsHolder").delegate("li", "click", function(){ ...
Also, all the appended li elements have the id of 't'. This will end up with invalid code as ids should be unique. Use a class instead if you want to have a group identifier.
.click() is not a live handler, is only binds the event to elements that exist in the DOM at the time of execution. If you want the events to be live, you'll need to look into another handler, such as .on()
When you call ("li").click(), you are binding events to the existing li elements. When you create new li elements, you need to bind them to the event so the click will work.
So, change your loop to something more like this...
$.each(data, function(i, item) {
var li = $('li').text(item.Description);
$(li).click(function(e) { loadChildren(this); });
$("#ResultsHolder").append(li);
});
The 'li' elements that are added to the page don't have the function bound to their click event handler. You need to use the jQuery live() function to do this.
http://api.jquery.com/live/
Basically rather than .click(function(){}) you need to do .live("click",function(){})
Because the binding the .click functionality to all li's happened before this new one was created. JQuery has the .on() function, which could solve your issue.
$("li").on("click", function(event){
// do functionality
});
Use .delegate() : $(document).delegate("li","click",function(){...})
Or, the newer version, .on() $('li').on("click",function(){...})
If your li's are in some fixed div, you can make it faster by replacing document in the first snippet with the selector of that div; and make the second one $(SELECTOR).on("click","li",function(){...})

Categories