ocajian
ocajian

Reputation: 687

Using a service in a directive (angularjs)

I've built an app with angularjs and created menu directives which get applied based on the view being loaded.

This is the structure of my menu directives:

angular.module('myApp')
 .directive('ogSection1Nav', function() {
  return {
    restrict: 'E',
    replace: true,
    templateUrl: '../scripts/directives/section1_nav.html',
    controller: function($scope, $location) {

      $scope.getClass = function(path) {
      var cur_path = $location.path().substr(0, path.length);
      if (cur_path === path) {
        if($location.path().substr(0).length > 1 && path.length === 1 )
          return "";
        else
          return "currentNav";
        } else {
          return "";
        }
      }

    }
  };
});

Template

<section class="adminMenu">      
  <nav class="side-nav">
  <ul>
      <li ng-class="getClass('/section1_summary')"><a href="#/section1_summary"><img title="Summary" src="images/summary.svg" title="Summary" height="25" /><span class="navText">Summary</span></a></li>
      <li ng-class="getClass('/section1_spot_list')"><a href="#/section1_spot_list"><img title="Spot List" src="images/postList.svg" title="" height="25" /><span class="navText">Spot List</span></a></li>
      <li ng-class="getClass('/section1_volume')"><a href="#/section1_volume"><img title="Volume" src="images/volumeHour.svg" title="" height="25" /><span class="navText">Volume</span></a></li>
      <li ng-class="getClass('/section1_location')"><a href="#/section1_location"><img title="Location" src="images/geography.svg" title="" height="25" /><span class="navText">Location</span></a></li>
      <li ng-class="getClass('/section1_media_type')"><a href="#/section1_media_type"><img title="Media Type" src="images/mediaType.svg" title="" height="25" /><span class="navText">Media Type</span></a></li>
   </ul>
 </nav>
</section>

The getClass function checks the current location and compares it to the path as defined in ng-class="getClass('/section1_volume')" on the li elements and attaches the currentNav class to the current page.

Now I have a whole bunch of these menu directives and don't want to always duplicate the same function in every directive so I set up a service as follows:

angular.module('myApp')

.service('MenuState', function($location) {

   this.getClass = function(path) {
     var cur_path = $location.path().substr(0, path.length);
     if (cur_path === path) {
     if($location.path().substr(0).length > 1 && path.length === 1 )
       return "";
     else
      return "currentNav";
     } else {
     return "";
    }
   };

}); 

I then call the getClass function in my directives as follows:

angular.module('portalDashboardApp')
  .directive('ogAdvertisingMediatracNav', function() {
    return {
    restrict: 'E',
    replace: true,
    templateUrl: '../scripts/directives/advertising_mediatrac_nav.html',
    controller: function($scope, MenuState) {
          $scope.getClass = MenuState.getClass();
       }
    };
}); 

However I get the following error: TypeError: Cannot read property 'length' of undefined

I take it this is because the path variable is not being passed to my service but I am unsure of how to get this service to pull in my path by going through the various ng-class="getClass('/path_name')"> sections of my menu templates

Upvotes: 0

Views: 94

Answers (3)

manasi sakhare
manasi sakhare

Reputation: 1051

@appdJava has proposed a good answer. Alternately, you could also do the following (need not call the getClass of MenuState, so remove parenthesis):

angular.module('portalDashboardApp')
.directive('ogAdvertisingMediatracNav', function() {
   return {
       restrict: 'E',
       replace: true,
       templateUrl: '../scripts/directives/advertising_mediatrac_nav.html',
       controller: function($scope, MenuState) {
           $scope.getClass = MenuState.getClass;
           }
       }
   };
});

Upvotes: 1

APD
APD

Reputation: 1519

This might work for you by delegating the call as:

angular.module('portalDashboardApp')
.directive('ogAdvertisingMediatracNav', function() {
   return {
       restrict: 'E',
       replace: true,
       templateUrl: '../scripts/directives/advertising_mediatrac_nav.html',
       controller: function($scope, MenuState) {
           $scope.getClass = function(path) {
               return MenuState.getClass(path);
           }
       }
   };
});

Upvotes: 2

Stefan van de Vooren
Stefan van de Vooren

Reputation: 2727

I do think the problem is in your service:

this.getClass = function(path) {
 var cur_path = $location.path().substr(0, path.length);
 if (cur_path === path) {
 if($location.path().substr(0).length > 1 && path.length === 1 )
   return "";
 else
  return "currentNav";
 } else {
 return "";
}

};

Your function getClass needs a variable 'path' and you don't apply this variable in your function call $scope.getClass = MenuState.getClass();

Upvotes: 0

Related Questions