1

I've the following html structure

<body data-page="first">
   <div class="start">Test</div>
</body>

and the following js

$('body[data-page="first"] .start').on('click',function (){
    body.attr('data-page','second');
});
$('body[data-page="second"] .start').on('click',function (){
    console.log('Test');
});

I would expect, that after the second click on .start, the console would show "Test", but it doesn't...

Can you tell me what I'm doing wrong?

Thanks in advance!

4 Answers 4

1

While you have your answer, I don't think the essential point has been made in any of the answers so far, and that is that the binding of an event handler must happen after the target element exists.

When you try to bind an event handler to a particular element in the DOM, the element must exist at the time. If it does not exist, the handler has nothing to bind to, and so the binding fails. If you later create the element, it's too late, unless you re-run the binding statement.

It will soon become second nature to call appropriate event handler binding statements after you create a new element (by modifying the HTML using javascript) that needs a handler.

For instance, in my current project I regularly make AJAX calls to a server to replace blocks of HTML as things happen on the page. Even if some of the new elements are exactly the same as the ones being replaced, they will not inherit any bindings from the replaced elements. Whenever I update the HTML I call a function that contains necessary statements to bind my event handlers to the new copy of the active elements.

Your code would work if you made the following change:

$('body[data-page="first"] .start').on('click',function ()
{
    body.attr('data-page','second');
    $('body[data-page="second"] .start').on('click',function (){
        console.log('Test');
    });
})

A couple of other (off-topic, but related) points:

  • It's possible to bind a handler to an element multiple times. The trick to avoiding this is to include the .off() method in the chain before binding (noting though that .off("click") will unbind all click handlers bound to that element, not just yours) e.g.

    $("#mybutton").off("click").click(function(){myHandler()});

  • "the arrow function doesn’t have its own 'this' value" () so don't use arrow functions in event handlers if you plan to reference any of the element's properties via 'this'. e.g.

    $("#mybutton").off("click").click(() => {console.log(${this.id})}); // >> "undefined"

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

Comments

1

The issue is that the page is rendered with the data-page set to first, and when you click again on it, that part of javascript still see "first", since is not rerendered, so you need a dynamic function, the read all the intereaction with that button, and than check wich value that attribute has. Like this you can make infinite cases, and still go on.

$('body .start').on('click',function (){
  const attr = $('body').attr('data-page');
  if(attr === 'first') {
    $('body').attr('data-page','second');
  } else {
    console.log('second');
   }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body data-page="first">
   <div class="start">Test</div>
</body>

And if you don't like the fact that is targetting all the "body" wich is weird, becouse you should have only 1 body, you can use an ID to target the right one

PS: is never a good idea to duplicate your function, if you can set everything in a dynamic function, that reads everything, is easier to debug in the feature, and is lighter and more clean to work on

Comments

0
$('body[data-page="first"] .start').click(function (){
       var body = $('body[data-page="first"] .start');
       body.attr('data-page','second');
    });

Comments

-1

This method can help :

var timesClicked = 0;
  $('.start').on('click',function (){
    timesClicked++;
    if (timesClicked>1) {
    console.log('Test');
    }
});

1 Comment

Thanks, but it's not so much about detecting the second click. It's more about using the updated data-attribute value in the selector.

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.