Jitendra Pancholi
Jitendra Pancholi

Reputation: 7562

stopPropagation & preventDefault are not working, parent click is still firing

In my code, I have added onclick on parent div and want to perform other action on inner div, but clicking on inner div also triggering parent click. how to stop that?

$(document).on('click', '.child', function(e) {
  e.preventDefault();
  e.stopPropagation();
  console.log('child');
});

function parentfun(sender) {
  console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent" onclick="parentfun(this)">
  parent
  <div class="child">child</div>
</div>
Above divs are generated on run time on some other event.

Clicking on child, also trigger parent's click. preventDefault & stopPropagation are not working.

FYI: my question is different than How do I prevent a parent's onclick event from firing when a child anchor is clicked?

Upvotes: 2

Views: 3661

Answers (4)

Dheeraj Kumar
Dheeraj Kumar

Reputation: 120

You can also resolve this problem by editing little bit in Your html code

<div class="parent" id="parent-div">

<!-- Just adding parent div text inside span tag -->

<span>parent</span>

<div class="child">child</div>

</div>

now go to jquery code

 $('.parent span').on('click',function(){

  //only print child text u can do more

  alert($('.child').text());

  //Change color of child

  $('.child').css('color','red');

});

Upvotes: 0

Esko
Esko

Reputation: 4207

What you are actually doing here is binding the click-event to the document, not the child-element. So the event has already bubbled up all the way to the document, it's too late to try to stop the bubbling with stopPropagation.

See here when I change the click-handler to the child instead:

$(".child").on('click', function(e) {
  e.preventDefault();
  e.stopPropagation();
  console.log('child');
});

function parentfun(sender) {
  console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent" onclick="parentfun(this)">
  parent
  <div class="child">child</div>
</div>

Edit

As the question changed a bit, here is what you can do (for example) if the elements are created dynamically:

  $(document).on('click', '.parent, .child', function(e) {
    e.stopPropagation();
    if ($(this).is(".child")) {
      console.log('child');
    } else {
      console.log('parent');
    }
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
  parent
  <div class="child">child</div>
</div>

Upvotes: 5

Sachin Bhandari
Sachin Bhandari

Reputation: 566

You can notice that when clicking the chlid element the parent triggers first (that is why parent prints first then child ) because of event capturing which precedes event bubbling. In-order to stop the event capturing phase from parent you can stop propagating that event and then only child event will trigger.

$(document).on('click', '.child', function(e) {
  //e.preventDefault();
  e.stopPropagation();
  console.log('child');
});

$(document).on('click', '.parent', parentfun);
function parentfun(e) {
  e.stopPropagation();
  console.log('parent');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
  parent
  <div class="child">child</div>
</div>

Upvotes: 0

connexo
connexo

Reputation: 56813

Using plain vanilla JS it works as expected:

function logEventTarget(e) {
  e.stopPropagation();
  console.log(e.target.id);
}

parentDiv.addEventListener('click', logEventTarget)
childDiv.addEventListener('click', logEventTarget)
<div id="parentDiv">
  parent
  <div id="childDiv">child</div>
</div>

Using an inline event handler won't pass the event to the handler function:

function logEventTarget(e) {
  e.stopPropagation();
  console.log(e.target.id);
}

childDiv.addEventListener('click', logEventTarget)
<div id="parentDiv" onclick="logEventTarget()">
  parent
  <div id="childDiv">child</div>
</div>

One of the many reasons you shouldn't use inline event handlers at all. Note that e.stopPropagation() still works for the childDiv.

Upvotes: 1

Related Questions