0

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

3 Answers 3

2

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);
           }
       }
   };
});
Sign up to request clarification or add additional context in comments.

1 Comment

Brilliant! That did the trick and the path variable now gets sent to the getClass function in my service
1

@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;
           }
       }
   };
});

3 Comments

Thanks so much for this solution. Could you perhaps explain the difference between $scope.getClass = MenuState.getClass; and $scope.getClass = MenuState.getClass() How are the two interpreted differently?
Yes. The difference is that, with $scope.getClass = MenuState.getClass() you are calling the getClass function of the MenuState service with no parameters and assigns the return value of the service function to $scope.getClass. This will create error while executing the function as there was a expected "path" param. But if you do a $scope.getClass = MenuState.getClass, it simply copies the function definition to the $scope and does not give eit a call. It is called only from the html where ng-class="getClass('some path')". Here it calls the function from $scope and not the MenuState
Aha, this makes sense. Thanks for expanding my coding knowledge
0

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();

1 Comment

Yeah this is the problem but I'm not sure how to pass that path value into the service

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.