2

I am using jquery 2.1.4

I dynamically create a list with hyperlinks to trigger a function.

$.getJSON('json_data.php', { method: 'getCertifications', userId: userId }, function(data) {
          $.each(data, function(key, value) {
             i++;
             $("#certificationCount").text("Total - " + i);
             $("#userCertifications").append('<div class="usercert"><li>' + value.certName + '</li><a href="#" data-id="' + value.certName + '">X</a></div>');
          });
      });

Then I want to call a function when a user clicks on the "X" hyperlink. However, the function is not being called.

$(document).ready(function() {
       $(".usercert a").on('click', 'a', function(e) {
          console.log("It works!");
          alert("It works!");
       });
    });

Why is the function inside the document ready not firing?

3
  • 1
    You are selecting .usercert a as your base element(s) for your delegated event handler. Are you sure that the element(s) exist when the binding occurs? If not, bind to an element that exists in the DOM when the binding occurs and use .usercert a as your delegated selector. Commented Sep 22, 2015 at 22:38
  • What Jasper said it the right line of thinking, since you said you are dynamically creating the elements, I doubt they exist when the binding happens. Commented Sep 22, 2015 at 22:39
  • I don't think the elements are binding because the ajax call is made after a user selects their username. Commented Sep 22, 2015 at 22:47

2 Answers 2

6

This boils down to what looks like a bit of a misunderstanding of delegated event handlers in jQuery.

You have:

$(".usercert a").on('click', 'a', function(e) {
   console.log("It works!");
   alert("It works!");
});

But you probably want:

$("#userCertifications").on('click', '.usercert a', function(e) {
   console.log("It works!");
   alert("It works!");
});

First you bind to an element that exists at the time of binding, in this case that would be the #userCertifications element (I make this assumption based on the fact that you are appending elements to this element in your AJAX callback). That way you've actually selected something, so the .on() method call is actually doing something.

Second you'd tell .on() what selector you'd like to match for your delegated event handler. In this case we'd use .usercert a because each of the elements we want to run the event handler for will match this selector: #userCertifications .usercert a.

Documentation for jQuery's .on(): http://api.jquery.com/on/#on-events-selector-data

Sign up to request clarification or add additional context in comments.

3 Comments

This makes sense, there elements are not present when the page loads and I don't reload the page so the binding doesn't occur for the links.
The explanation provided here is the clearest I've run across on explaining delegated events. Or perhaps the way he expressed it finally gave me that light-bulb moment. In any case, I was loading in some content via a handlebar template so the item I was attaching to wasn't firing. Rewriting my listener as a delegated event instead of an .on event resolved my issue.
2

$(document).ready is firing before you make your asynchronous call, so those hrefs haven't yet been populated. Rebind the clicks after you fetch your data.

1 Comment

The code in question uses a delegated event handler which just needs its selectors fixed. If you use the suggested solution in this answer you do not need a delegated event handler as the elements will already exist in the DOM.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.