Q:

AngularJS: Using services in directives

This is an angularjs app.  I have a service that handles the loading of content (ajax).   While the service is getting the content, a number of things throughout the app hide, later showing again (depending on the content returned).   They might have the same scope, different scope, whatever.   They just need to hide while content is loading, and then show when it's done.  Pretty normal stuff. 
Right now, I have separate controllers watching a "loading" property of the service and using regular angular directives (ng-show, ng-hide, etc.)  to show/hide.   But this feels like overkill.   I'd prefer to write a custom "loading" directive that injects the loading service and does the watching and showing/hiding. 
My question is: Is what I want to do "bad"?   The controller way, I end up boilerplating a bunch of code, maybe up to like 5 or 6 times, or even more as the app grows.   The custom directive way, I write it once and use an attribute where I need it.   Yeah - there's a dependency on that service, but that just doesn't feel like the end of the world that some people have made me start to think I should think it is. 
For what it's worth, I feel like I've heard "separation of concerns" so many times I've become paralyzed by it.   It leads me to overthink everything because I want to do things the right way, but it sure doesn't feel like I'm being very productive. 

A:

If I understood correctly, you have a bunch elements that should hidden when a particular service is loading data, and then be displayed again when the data is loaded, right? 
In that case, events might be a good solution:

they can be global to the appliciation (which i think is what you are aksing for). 
they allow for avoiding direct coupling between elements (also one of your concerns). 

So, in your service, just broadcast events when stuff happens:
$rootScope.$broadcast('loading-data');
axajStuffOrWhatever(function() {
   $rootScope.$broadcast('data-loaded');
});

Then, wrap the show/hide behaviour in a directive that will listen to those events. 
.directive('hideWhileLoadingData', function() {
  return {
    link: function(scope, el, attrs) {
      scope.$on('loading-data', function() {
        el.css('display', 'none');
      });
      scope.$on('data-ready', function() {
        el.css('display', 'block');
      });                
    }
  };  
});

Use the directive:
<div hide-while-loading-data>something</div>

The advantage of using events here, is that later on, they could be originated by a different service, or by multiple services, and the directive will not be affected by that as long as the events are the same. 
For more complex behaviour, you could also parametrize the events and the directive, so different elements will react to different kind of stuff. 
I've made an example of this.