Why you Should Always use jQuery’s .on(‘click’) instead of .click

      I would like to start by saying that despite the title of this post, what I am about to write does not apply only to .click, but to every jQuery event that can be called in the same way. Other examples would be: .focus(), mouseenter(), keydown(), keypress(), etc. I am using .click because it’s quite simple to demonstrate, and because it’s one of the most used event handles.

      Now you might be asking yourself why would you use .on('click’) instead of .click given that the it’s so much easier to type button.click(function(){};) as opposed to $(‘body’).on(‘click’, ‘button’, function(){});. The jQuery api itself describes the .click method as a “a shortcut for .on( "click", handler )”. The problem I have with that description is that there are situations in which these two methods will not act in the same way. This can cause a lot of headaches in the debugging steps, and any time you might save by typing fewer characters might cost you hours chasing down this bug.

      As has been a pattern on my previous posts, let’s start with a simple code demonstration. What would you expect the code below to log if we loaded this page and then clicked on the test button:

<html>
    <body>
        <div class="test"></div>
        <script src="bower_components/jquery/dist/jquery.js"></script>
        <script src="test3.js"></script>
    </body>
</html>

$(document).ready(function(){
  $('button').click(function() {
    console.log("It worked");
  });
  $('.test').html('<button>Test</button>');
});

      Before we actually answer this question, let’s look at what’s going on. The script is run and we get to the .click method. Here we are attaching the .click method to the button, but if you look at the html the button does not exist yet so we are attaching the .click method to an inexistent element. The button element would then be added to the .test class, but it would not have the .click method bound to it. So if you did load this page and tried to click on the test button it would not do anything.

      Not let’s look at the same example with the $(‘body’).on(‘click’, ‘button’, function(){}); what would you expect this to log out if we printed the loaded the page and clicked on the button:

<html>
    <body>
        <div class="test"></div>
        <script src="bower_components/jquery/dist/jquery.js"></script>
        <script src="test3.js"></script>
    </body>
</html>

$(document).ready(function(){
  $('body').on('click', 'button', function() {
    console.log("It worked");
  });
  $('.test').html('<button>Test</button>');
});

      This would log out “It worked”. Let’s look at what’s going on here and why this would actually work. When this script runs and we reach the .on method we are telling the program that if a ‘button’ element inside ‘body’ is ever clicked then run the handler function. We are now attaching the event to the existing ‘body’ element which is guaranteed to exist at the time the documents was created. Using .on(‘click’) instead of .click also gives you the option of removing the events bound to that element by using the .off() method which removes event handlers attached to that element. For more information on using the .off() method please look at the jQuery api. I hope this blog post was enough to get you to stop using the .click method and I would also like to remind you that the same applies to other events some of which I have referred to in the beginning of this post.

Paulo Diniz