jQuery code doesn't work on dynamic content loaded with ajax

Hello everybody,

So here’s my first post on this forum, let’s see how this works! I really hope anyone out here can help me with this struggle I’m in. Let me try to explain it:

I have an index.php with thumbnails of a few projects, followed by the full content of one of those projects.There’s some jQuery in the index that I use on the content in this page. Everything works fine when the project content is hard-coded into the index, but I want it to load dynamically through an AJAX call. I got that working too, it loads the content from the database without reloading the page, but then I run into my problem: none of the jQuery works on the ‘new’ content.

I use two separate files to get the content: xmlhttp.js with a function that is fired when you click on one of the thumbnails on the index. This uses a separate .php file with a mysql request to get the right content, and then injects this response into the right element on the index.

Does anyone have an idea where I go wrong? Thanks a lot for your time in advance.

Hugo

1 Like

When you say that none of your jQuery works on the dynamically loaded content, do you mean things like click event handlers etc?

Well, the onclick event to get the right content does work (which is plain inline javascript) but the jQuery event on that same click to automatically scroll down for example does not work.

Could you share either a link to the page (if it’s online) or the HTML and JS for the page?

Hi there,

If I understand this correctly, you are inserting content into the DOM, but the required behaviour is not being attached to the inserted elements.

The solution to this is to use jQuery’s .on() method, but to bind it to an element that exists when the page is first rendered.

An example:

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>jQuery scaffold</title>
  </head>
  
  <body>
    <button class="clickMe">Click Me!</button>
  
    <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
    <script>
      $(function(){
        $(".clickMe").on("click", function(){
          $("<button>",
            {
              class: "clickMe",
              text: "Click Me!"
            }
          ).appendTo("body");
        });
      });
    </script>
  </body>
</html>

Here, when you click the original “Click Me!” button, it will insert another (identical) button into the page.
The problem is that these inserted buttons do nothing when clicked, the behaviour of the original button was not attached to them.

Now, if we change the click handler to this:

$(document).on("click", ".clickMe", function(){

the new buttons will also have the behaviour of the original button.

In this case we have bound the click event handler to an element that existed when the page was rendered (document) and specified a selector string to filter the descendants of the selected element that triggers the event.

<!DOCTYPE HTML>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>jQuery scaffold</title>
  </head>
  
  <body>
    <button class="clickMe">Click Me!</button>
  
    <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
    <script>
      $(function(){
        $(document).on("click", ".clickMe", function(){
          $("<button>",
            {
              class: "clickMe",
              text: "Click Me!"
            }
          ).appendTo("body");
        });
      });
    </script>
  </body>
</html>

http://api.jquery.com/on/

I hope that helps and is relevant to your issue, but as fretburner said, it would really help to see some code.

Also, please note, that prior to jQuery 1.7, this behaviour was achieved using the now deprecated .live() method.

Hi guys, thanks for helping out. I’m not sure if the .on() method is the key, but let’s see. Here’s the example page: http://www.11amtoday.nl/work/

These are the functions that are called with onclick() on the links, the first one to generate the project thumbnails when you click on ‘latest’ or ‘featured’, the second one if you select one project:

function selectProjects(str) {
	var xmlhttp;
	if(str=="") {
	  document.getElementById("projects").innerHTML="";
	  return;
	}
	if(window.XMLHttpRequest) { // modern browsers
		xmlhttp=new XMLHttpRequest();
	} else { // IE6, IE5
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}
	xmlhttp.onreadystatechange=function() {
		if(xmlhttp.readyState==4 && xmlhttp.status==200) {
			document.getElementById("projects").innerHTML=xmlhttp.responseText;
		}
	}
	xmlhttp.open("GET","projects.php?projects="+str,true);
	xmlhttp.send();
}

function selectWork(str) {
	var xmlhttp;
	if(str=="") {
	  document.getElementById("project").innerHTML="";
	  return;
	}
	if(window.XMLHttpRequest) { // modern browsers
		xmlhttp=new XMLHttpRequest();
	} else { // IE6, IE5
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}
	xmlhttp.onreadystatechange=function() {
		if(xmlhttp.readyState==4 && xmlhttp.status==200) {
			document.getElementById("project").innerHTML=xmlhttp.responseText;
		}
	}
	xmlhttp.open("GET","project.php?project_id="+str,true);
	xmlhttp.send();
}

If I don’t use this AJAX request but just put the php straight into the index to display one of the items, the jQuery does work. What the jQuery does is automatically scroll down the page to the project, make sure the divs surrounding the project text and the side info next to it have the same height, and create a photo slider if there is more than one image to be displayed.

OK, so here’s one way you could do it. Change the links on your project thumbnails, removing the onclick handler, and adding a data attribute for the project ID, like this:

<a href="#" data-project-id="3" class="down"> ... </a>

Then you can add this JS:

$("#projects").on('click', 'a', function(e) {
    e.preventDefault();
    var projectId = $(this).data('projectId');
    $('#project').load('http://www.11amtoday.nl/work/project.php?project_id='+projectId, function(){
        $.scrollTo("#overview", 200);
    });
};

This attaches a click handler to all the project thumbnails, which loads in the relevant section of HTML dynamically, and then scrolls down to it. You might as well use jQuery, seeing as you’re already including it in the page, and it means you can do away with a lot of the code from the xmlhttp.js file.

Wow thanks guys, that did get it working. I’d never heard of data-project-id before and didn’t really know about the .on() method. After the .scrollTo() I added all other jQuery that has to be attached to the project as well and works perfect, except for the Twitter and Facebook buttons. I had actually been struggling with that before, it works when I load the mysql content straight into the page but not when it’s loaded via AJAX, and I can’t add their scripts to jQuery of course. Any ideas how to get those in there?

By the way, you missed a closing ‘)’ in your last line. But thanks so far, this really helped me a lot already.

To activate the Facebook and Twitter widgets, add the following code to the callback that runs after the content is loaded:

FB.XFBML.parse(document.getElementById('project'));
twttr.widgets.load();

Thanks! That works, only now both buttons link to the main page and not the specific item that is being displayed.
Do you think that it is possible with this setup to add an url with something like ?project_id=3 to the FB and Twitter buttons? I now added a page similar to project.php to display one item if the url has a project_id variable, so the buttons can maybe connect to that link?

Cheers