40

In the following example:

  <li ng-repeat="item in items" ng-click="showItem(item)">
    <h3>{{item.title}}</h3>
    <button ng-click="remove(item)">Remove</button>
  </li>

When I click on the button showItem() also is invoked due to event bubbling. I know that I can use $event to watch for $event.currentTarget and do $event.stopPropagation() etc. but this is very ugly.

Btw. I don't want to stop propagation on the button (In my case the button is a twitter bootstrap dopdown/button - this is just an example)

How do I stop showItem() from beeing called when I click on the remove button?

EDIT The ugly fix would be to have:

function remove(item,$event){
  $event.originalEvent.prevent = true;
  // rest of the code
}

function showItem(item,$event){
  if($event.originalEvent.prevent)return;
  // rest of the code
}
1
  • If you can't use stopPropagation, you will have to restructure your dom so they're not nested. Is that possible? Commented May 22, 2013 at 21:21

2 Answers 2

63

This solution worked for me (I'm only supporting recent browsers, so I tried to modify the code to be more retro-compatible):

HTML:

<li ng-repeat="item in items" ng-click="showItem(item)">
    <h3>{{item.title}}</h3>
    <button ng-click="remove(item, $event)">Remove</button>
</li>

Scripts:

function remove(item, $event) {
    // do some code here

    // Prevent bubbling to showItem.
    // On recent browsers, only $event.stopPropagation() is needed
    if ($event.stopPropagation) $event.stopPropagation();
    if ($event.preventDefault) $event.preventDefault();
    $event.cancelBubble = true;
    $event.returnValue = false;
}
function showItem(item) {
    // code here
}

EDIT - Added a JSFiddle demo to try it out http://jsfiddle.net/24e7mapp/1/

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

7 Comments

This method didn't work for me on Chrome Version 35.0.1916.153 m, but $event.stopPropagation() did. I didn't need the $event.returnValue.
Exactly. In Chrome (and other modern browsers), you can stop at the first line: $event.stopPropagation(); (without the 'if'). But as specified in the comments, if you need to make it work in IE8 et less, you have to use $event.preventDefault() or the cancelBuble/returnValue. Maybe one of those two aren't required, I can't remember exactly.
@Ron, please check out the demo and try it on different browser versions.
Both $event.cancelBubble = true; and $event.returnValue = false; breaks Chome/ium (tested on 43.0.2357.130).
@arcol You could simply to a check before, like so: if ($event.cancelBubble) { $event.cancelBubble = true; }.
|
0

showItem can be updated to return early if the passed in item no longer exists:

function remove(item) {
  if (-1 == $scope.items.indexOf(item)) {
    // Item no longer exists, return early
    return;
  }
  // Rest of code here
}

Comments

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.