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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With