Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular UI-Router ui-sref ignore some elements

I have an interesting problem with the uiSref directive and I haven't been able to find a solution (well an elegant one anyway) anywhere on the web. Basically I have a requirement from a client to be able to click a row in a table of resources and go to the editing view for that resource. Normally the uiSref directive works beautifully, but the problem resides in the fact that I have a Bootstrap dropdown in the last <td> of the table with a bunch of quick actions in it. The 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 on the button in the actions column, the uiSref overrides the default action of the dropdown and takes me to the edit page. Now you might be asking yourself "well that's easy, why can't you just stop the propagation of the event!?"... doesn't work. When I add this to the actions column:

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

It kills the functionality of the dropdown menu and nothing shows up. Right now I have a workaround in place where I define an ngClick on the <tr> element that then deciphers where the state should go depending on the element clicked like so:

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

And The 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 though and I have a lot of list views like this. All I'm looking for is an elegant and portable solution that hopefully works natively through UI Router like $event.stopPropagation() (Although I've poked through the UI Router source and can't seem to find a workable alternative). Basically I want to have my cake and eat it too. Anyway, it'll be interesting to see what the SO community can come up with or if what I'm asking for is not currently possible. Thanks!

like image 409
Mike Quinlan Avatar asked Jul 16 '14 14:07

Mike Quinlan


1 Answers

I got it! While looking through the UI Router source some more, it appears that the click event will be ignored if the target attribute is populated on the element that the uiSref resides on. It may not be the most beautiful thing in the world, but it sure is easier than what I was doing before.

NOTE: This only works if you're using 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 for just 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 implications of this.

like image 54
Mike Quinlan Avatar answered Sep 25 '22 19:09

Mike Quinlan