on() and bind() are not working

Asked

Viewed 163 times

2

I’m using off() in an element to disable its functionality and need to enable it again with on(). But it’s not working when on() is executed...

Here’s the code, I’m trying to prevent a form from being sent twice when it’s clicked on a button:

$("#meuBotao").click(function (e) {
    $(this).off("click");
    $.ajax({
    url: "/page",
    type: "POST",
    complete: function() {
                    $(this).on("click");
    },
                ...

What am I doing wrong? I tried with on() and off(), and with bind() and unbind() also (who are deprecated for older versions now, but it should still work).

2 answers

3


As I understand it, you want to disable the button while AJAX is running so the user can’t fire multiple requests, correct? In this case it could be done so:

 $("#meuBotao").on('click',function(){
    var el = $(this);
    el.prop('disabled',true); //desabilita o botão
    $.ajax({
    url: "/page",
    type: "POST",
    complete: function(){
        el.prop('disabled',false); //habilita botão novamente
    },
    //...

Note that I have created a new variable el to handle the element $(this), so that it works properly even within other scopes (as in the case of the function fired in the complete ajax).

I also switched .click() for .on('click') because this second is more recommended by several reasons.

  • 1

    In this case it makes no difference to use click or on.

  • @bfavaretto In fact, giving a boring, has yes, it is proven that and method .on() is plus performatic, therefore, even without taking full advantage of the functionalities of this method, it is still advantageous to use it.

  • 1

    The very test you linked shows that this is not true. There is only a difference in performance between using delegation or not.

  • I think use .on or .click in this case is irrelevant and I do not believe I am more recommended here. The .on how linkou is used to delegate events, which does not apply here.

  • @Sergio o .on is not limited to the use with delegation of events, in fact the use of it in place of ancient delegates is even encouraged in the blog itself jQuery.

2

The main problem here is that the this inside the ajax function is not the same as the this out of the function. The scope is different... This has easy solution, which is to create an intermediate variable that points to the same object:

$("#meuBotao").click(function (e) {
    $(this).off("click");
    var self = this; // assim guardamos o apontador no "self"
    $.ajax({
        url: "/page",
        type: "POST",
        complete: function() {
            $(self).on("click"); // aqui usa o "self". Já agora, aqui falta a função a correr quando o click fôr gerado
        },
            ...

Apart from this detail there are other more commonly used ways to prevent clicks, rather than removing and adding events. One of them is to create a flag/flag as property in the element or a variable that stores the information of whether the element can be clicked or not.

An example of this would be:

$("#meuBotao").click(function (e) {
    if (!$(this).data('clicavel')) return false;
    $(this).data('clicavel', false);
    var self = this; // assim guardamos o apontador no "self"
    $.ajax({
    url: "/page",
    type: "POST",
    complete: function() {
          $(self).data('clicavel', true);
    },
                ...

You can even do the same by adding CSS pointer-events: none; in a class, or directly in the element. You can see more ideas in this answer: /a/2353/129

Note: in your code $(this).on("click"); the second parameter of the function indicating which code to run when the click is received is missing...

  • 1

    Thank you very much!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.