10

How to create the issue:

  1. click on existing trigger links - something happens (pass)
  2. click on the "add trigger" button, which appends a new trigger link w/ same class
  3. click on the newly created link, and it does not do the same thing as the 1st 2 links that existed from the start (fail)

Here is my example -: http://jsbin.com/equjig/3/edit

I thought the .on('click', func) function was good for adding events to current elements in the dom, but also for future elements that get added to the dom?

Here is my current javascript :

$(document).ready(function() {
  $(".link").on('click', function(e) {
    e.preventDefault();
    $("#out").append("clicked<br/>");
  });

  $("#b1").on('click', function() {
    $("#p1").append("<a href='#' class='link'>new trigger</a>");
  });

here is the HTML

<button type="button" id="b1">add trigger</button>
  <p id="p1">
    <a href="#" class="link">trigger 1</a>
    <a href="#" class="link">trigger 2</a>
  </p>
  <div id="out"></div>

Note - im using jQuery 1.7

Thanks!

Manse
  • 37,765
  • 10
  • 83
  • 108
Ian Davis
  • 19,091
  • 30
  • 85
  • 133
  • 7
    Wow, apparently nobody knows that jQuery 1.7 deprecates live. No more live answers! – mrtsherman Nov 29 '11 at 18:50
  • @mrtsherman Or nobody felt it was reasonable to go to jsbin, check the jQuery version OP was using, and differentiate it from the three other versions also loaded. My guess is quite a few people know, but tend to rely on more-complete questions--which I believe is reasonable. Questions should include versions, and the code, particularly when it's this short. – Dave Newton Nov 29 '11 at 18:54
  • 2
    @DᴀᴠᴇNᴇᴡᴛᴏɴ - I thought it was pretty clear. `On` did not even exist prior to 1.7 so he had to be using it. He provides the code he used `.on('click', func)` – mrtsherman Nov 29 '11 at 18:58
  • @DᴀᴠᴇNᴇᴡᴛᴏɴ i agree with you - if the code was within the question then less incorrect answers would have been added .... but mrtsherman is correct - `on` was already being used ... albeit incorrectly ! – Manse Nov 29 '11 at 18:59
  • @mrtsherman I'm glad you did. IMO questions should be complete; we'll need to agree to disagree on that. – Dave Newton Nov 29 '11 at 19:00
  • @All question updated for clarity ... – Manse Nov 29 '11 at 19:02
  • @DaveNewton - I included a link to a demo which has all the code in it. I thought that would suffice. – Ian Davis Nov 29 '11 at 19:04
  • @IanDavis no probs ... but remember that you caused all this fuss :-) lol and that in future you need to add the import bits of code and detail to your questions .... – Manse Nov 29 '11 at 19:10

6 Answers6

16

You are almost there with on ...

working example : http://jsbin.com/equjig/6/edit

$(document).ready(function() {
    $('#p1').on('click','.link', function(e) {
        e.preventDefault();
        $("#out").append("clicked<br/>");
    });
});

This will work - you should select a parent div of the .link elements (i have used $('#p1') here, like in your jsbin)

Jasper
  • 75,717
  • 14
  • 151
  • 146
Manse
  • 37,765
  • 10
  • 83
  • 108
4

.on() can also behave like .delegate() which is used like this:

//#p1 is the context and .link is what will be bound to as long as the .link element is a descendant of #p1
$('#p1').on('click', '.link', function(e) {
    e.preventDefault();
    $("#out").append("clicked<br/>");
});

Here's documentation for .on(): http://api.jquery.com/on

Jasper
  • 75,717
  • 14
  • 151
  • 146
4

According to the api docs for on the signature .on('click', func) replicates .bind's behaviors - that is to say, it binds the listener to each and every existing element in the collection.

To get .delegate behaviors - that is, to bind to each and every event that originates from a specific kind of (child) element, include a selector:

$("parent-selector").on('click', 'your-selector', func)
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • @Ian Davis - of course, you'll need to make sure you are using 1.7 - `on` doesn't exist in earlier versions of jQuery. – Sean Vieira Nov 29 '11 at 18:51
  • 2
    +1 - nice answer. In OP's case something like this would work - `$("#p1").on('click', '.link', function(e)` – mrtsherman Nov 29 '11 at 18:52
  • 1
    He is .... check out the jquery hes using -> /*! jQuery v1.7.1 jquery.com | jquery.org/license */ – Manse Nov 29 '11 at 18:52
2

You can use .on() from version 1.7, and it also somewhat replaces the old .live() except in how you provide the syntax.

Using .on() you can delegate the event to any parent element like this:

$(document.body).on('click','.link',function() {
    // handler for all present and future .link elements inside the body
});

This way, it will also work for future elements that are added inside the body that has the className 'link'.

I made a small modification to your lint that works the way you expect: http://jsbin.com/adepam. And here is the code:

$(document).ready(function() {
  $(document.body).on('click', '.link', function(e) {
    e.preventDefault();
    $("#out").append("clicked<br/>");
  });
  $("#b1").on('click', function() {
    $("#p1").append("<a href='#' class='link'>new trigger</a>");
  });
});
David Hellsing
  • 106,495
  • 44
  • 176
  • 212
0

The onclick event applied only to the elements that already exist. You need to use .live function.

emco
  • 4,589
  • 3
  • 18
  • 20
-2

Change the .on() to .live()

$(document).ready(function() {
  $(".link").live('click', function(e) {
    e.preventDefault();
    $("#out").append("clicked<br/>");
  });

  $("#b1").on('click', function() {
    $("#p1").append("<a href='#' class='link'>new trigger</a>");
  });
});
Pastor Bones
  • 7,183
  • 3
  • 36
  • 56