简体   繁体   中英

Angular js stop propagation from Bootstrap “dropdown-toggle” event

I have an Angular JS 1.3 app.

In it I have a table row repeater with an ng-click:

<tr ng-repeat-start="user in users.users" ng-click="showDetails = !showDetails">
 <!-- main row, with the menu td shown below -->
<tr class="row-details" ng-show="showDetails" ng-class="{ 'active': showDetails }">
    <td>this is the row that hows details</td>
</tr>
<tr ng-repeat-end></tr>

Which toggles opening a detail view. Works fine. But now I need to add another item in each of the td s, a Bootstrap button menu:

<td>
<div class="btn-group">
  <div ng-switch on="user.status">
    <button class="btn btn-link btn-gear dropdown-toggle" type="button" data-toggle="dropdown"><i class="fa fa-cog"></i></button>

      <ul class="dropdown-menu dropdown-menu-right" role="menu" ng-switch-when="Inactive">
        <li><a href="" ng-click="users.modals.deleteUser()">Delete</a></li>
      </ul>

      <ul class="dropdown-menu dropdown-menu-right" role="menu" ng-switch-when="Invited">
        <li><a href="" ng-click="users.toast.resendInvite()">Resend invitation</a></li>
        <li><a href="" ng-click="users.modals.deleteUser()">Delete</a></li>
      </ul>

      <ul class="dropdown-menu dropdown-menu-right" role="menu" ng-switch-default>
        <li><a href="" ng-click="users.toast.sentPassword()">Reset password</a></li>
        <li><a href="" ng-click="users.modals.deleteUser()">Delete</a></li>
      </ul>
  </div>
</div>
</td>

Problem is, trying to click on this menu button instead triggers the ng-click on the row, toggling the row state but never opening my menu. How can I prevent this?

This is pretty tricky problem. The thing is that when you click menu button two things happens: the first is that it opens Bootstrap dropdown menu, and the second is that event propagates to the parent element and also triggers showDetails = !showDetails .

The obvious solution is to try to stop event propagation with $event.stopPropagation() on the td level, so that event doesn't bubble up the DOM tree and never triggers parent ngClick . Unfortunately, it will not work because Bootstrap sets up click event listener on the document element to benefit from bubbling, so you can't stop propagation.

The simplest solution I came up with in such cases is to set a flag on the original event object whether event occurred on the menu button. If this is the case ngClick on the tr won't do anything.

It will look like this for tr :

<tr ng-repeat-start="user in users.users" ng-click="$event.originalEvent.dropdown || (showDetails = !showDetails)">

ans for button :

<button ng-click="$event.originalEvent.dropdown = true" class="btn btn-link btn-gear dropdown-toggle" type="button" data-toggle="dropdown">
    <i class="fa fa-cog"></i>
</button>

Demo: http://plnkr.co/edit/eIn6VW3Y2jHn0MtJQVcU?p=preview

With help of dfsq's answer I managed solve same kind of problem in Angular 2. Here is my sample code.

<td class="tablerowdata" (click)="$event.dropdown || onSelect(track)" >

<button (click)="$event.dropdown = true" type="button" class="btn btn-default dropdown-toggle trackbuttons" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM