Angular UI-Router ui-sref ignores some elements

I have an interesting problem with the uiSref directive, and I could not find a solution (well, elegant anyway) anywhere on the Internet. Basically, I have a requirement from the client to be able to click a row in the resource table and go to the edit view for this resource. The uiSref directive uiSref works beautifully, but the problem is that I have a Bootstrap popup in the last <td> table with a bunch of quick actions in it. HTML looks something like this:

 <table class="table table-bordedered table-hover"> <thead> <tr> <td>Name</td> <td>Actions</td> </tr> </thead> <tbody> <tr ng-repeat="resource in resources" ui-sref="edit({id: resource.id})"> <td ng-bind="resource.name"></td> <td class="actions-column"> <div class="btn btn-xs btn-default" data-toggle="dropdown"> <i class="fa fa-cog"></i> </div> <ul class="dropdown-menu pull-right"> <li> <a href="javascript:void(0)" ng-click="doSomethingCrazy(resource)">SOMETHING CRAZY</a> </li> </ul> </td> </tr> </tbody> </table> 

The problem is that when I click the button in the action column, uiSref overrides the default action in the drop-down list and takes me to the edit page. Now you can ask yourself, "well, that’s easy, why can't you just stop distributing the event!?" ... doesn’t work. When I add this to the action column:

 <td class="actions-column" ng-click="$event.stopPropagation()"> 

It kills the functionality of the dropdown menu and nothing appears. Right now I have a workaround where I define ngClick on the <tr> element, which then decrypts where the state should go, depending on the element clicked like this:

 <tr ng-repeat="resource in resources" ng-click="goToEdit(resource, $event)"> 

And JS looks like this:

 scope.goToEdit = function(resource, event) { // if the event.target has parent '.actions-column' or is that column, do nothing else // invoke $state.go('edit', {id: resource.id}) } 

I hate it, although I have many lists like this. All I'm looking for is an elegant and portable solution that we hope works through the UI Router, for example, $event.stopPropagation() (although I made my way through the source of the UI interface and cannot find a suitable alternative). Basically, I want to have a cake and eat it too. In any case, it will be interesting to see what the SO community has to offer, or if what I ask is currently not possible. Thanks!

+6
source share
1 answer

I understood! When viewing the source of the UI interface a little more, it seems that the click event will be ignored if the target attribute is filled with the element on which uiSref is located. It may not be the most beautiful thing in the world, but it is certainly easier than what I did before.

NOTE. This only works if you use the whole jQuery library, not jQLite

So, I wrote this directive:

 app.directive('uiSrefIgnore', function() { return { restrict: 'A', link: function(scope, elem, attrs) { elem.on('click', function(e) { // Find the ui sref parent var uiSref = elem.parents('[ui-sref]').first(); // Set the target attribute so that the click event is ignored uiSref.attr({ target: 'true' }); // Function to remove the target attribute pushed to the bottom // of the event loop. This allows for a digest cycle to be run // and the uiSref element will be evaluated while the attribute // is populated setTimeout(function() { uiSref.attr({ target: null }); }, 0); }); } }; }); 

That way, whenever I want to ignore the javascript event only for the uiSref directive, I can just add this to the html:

 <tr ui-sref="edit"> <!-- any other elements --> <td ui-sref-ignore>The element I care about</td> </tr> 

Boom! Let me know what you guys think about the consequences of this.

+6
source

Source: https://habr.com/ru/post/972328/


All Articles