1

index.html

<body ng-app="dnaClientApp" ng-controller="MainCtrl">
<ul class="nav navbar-nav navbar-collapse">
    <li ng-repeat="item in menu" ng-class="{active: item.route === menuActive }"><a href="#{{item.route}}">{{item.label}}</a> 
    </li>
</ul>

MainCtrl main.js

.controller('MainCtrl', function ($scope, $route, $rootScope, $location, $cookies, translationSvc, $http, $cookieStore, UserService) {

       if (typeof $scope.selectedLanguage === 'undefined') {

            $scope.selectedLanguage = 'fi';//Default language

        }
        translationSvc.getTranslation($scope, $scope.selectedLanguage);


        $scope.menu = translationSvc.getMenu($scope.selectedLanguage);//Creating menus dynamically
        console.log('$scope.menu-->' + $scope.menu + ' length: ' + $scope.menu.length);

        $scope.menuActive = '/';

        $rootScope.$on('$routeChangeSuccess', function (e, curr, prev) {
            $scope.menuActive = $location.path();
        });

translationSvc

var getMenu = function($scope, language) {
        if (language === 'fi' && typeof $rootScope.userRole !== 'undefined' && typeof $rootScope.userRole.currentUserRole !== 'undefined' && $rootScope.userRole.currentUserRole.userRole === 3 ) {

            $scope.menu = [
                {label: 'Home', route: '#/'},
                {label: 'DNA', route: '#/dna'},
                {label: 'Dna-list', route: '#/dna-list'},
                {label: 'Admin', route: '#/admin'}

            ]

        }else...

Routes after login goes here, menu is in index.html

.config(function ($routeProvider) {
$routeProvider
  .when('/', {
    templateUrl: 'views/main.html',
    controller: 'MainCtrl'
  })

Question

If I check the length of menu array in controller, everything is ok, but my menus in header are all the same, default menus (3 menus, not 4). What am I doing wrong or why I can't update menus dynamically? Idea is to get different menus for different roles, like administrator could see a admin menu as well etc. Any other working ideas to get this done?

4
  • From where are you trying to modify $scope.menu ? Are you in the same controller ? MainCtrl ? Commented Jun 12, 2015 at 15:55
  • I call translationSvc from main controller and I create there dynamically menu and put it to the $scope. There is that else with three dots, it means that there is more options, but I save the code :) Commented Jun 12, 2015 at 16:00
  • Are all the tests in the if statement met? Commented Jun 12, 2015 at 16:00
  • Before login scope.menu in cosole is: $scope.menu--> length: 3 and after login with admin role $scope.menu-->length: 4 and I checked with debugger that everything is fine, but menu is always the same. Commented Jun 12, 2015 at 16:14

3 Answers 3

2

I don't like the idea of passing around $scope to services. It makes the service very confusing to read because you don't know what data it's changing. Instead, why not just build the menu in translationSvc.getMenu() and return it to MainCtrl. I don't see why something like this shouldn't work unless code that you didn't post is doing something else.

Controller:

.controller('MainCtrl', function ($scope, $route, $rootScope, $location, $cookies, translationSvc, $http, $cookieStore, UserService) {
    ...

    // Creating menus dynamically
    $scope.menu = translationSvc.getMenu($scope.selectedLanguage);

    ...
}

translationSvc:

var getMenu = function(language) {
    var newMenu = []

    if (language === 'fi' && typeof $rootScope.userRole !== 'undefined' && typeof $rootScope.userRole.currentUserRole !== 'undefined' && $rootScope.userRole.currentUserRole.userRole === 3 ) {

        newMenu = [
            {label: 'Home', route: '#/'},
            {label: 'DNA', route: '#/dna'},
            {label: 'Dna-list', route: '#/dna-list'},
            {label: 'Admin', route: '#/admin'}
        ];

    } else if (...) {
        newMenu = [...];
    } else {
        newMenu = [...];
    }

    return newMenu;
}

I think you were running into issues where you're updating the $scope outside of angular's realm, i.e. angular had no way of knowing that you were changing the $scope in translationSvc so your changes were not propagated to your view (index.html).

I also recommend editing translationSvc.getTranslation() along the same lines and remove passing the $scope to that function as well.

Sign up to request clarification or add additional context in comments.

2 Comments

I rewrite the code so I don't pass the scope anymore, but the result is the same. I checked with debugger that menu in the scope is correct one, but index.html is always the same. $routeProvider for / goes to main.html and menu is in index.html.
I figured it out that if user changes the language, menus are correct. So it needs $route.reload(); call to work correctly. But if I add this to mainCtrl init, it is eternal loop.
0

I assume that the digest loop is not performed when you change your menu.

Wrap it into $timeout to force the digest loop and do not forget to add $timeout as a dependency

$timeout(function(){
$scope.menu=translationSvc.getMenu($scope, $scope.selectedLanguage);//Creating menus dynamically
});

1 Comment

No help, but thank you anyway for idea. I think that I got some kind of logical mistake with scope between index.html and main.html as a part of index.html. This is irritating. Any other ideas for creating menus dynamically or get this working? BTW, what is the digest loop :)
0

I added $viewContentLoaded and it started to work. There is that login-system between pages and I think that it might be a problem with restricted routes etc.

$scope.$on('$viewContentLoaded', function() {
            $scope.menu = translationSvc.getMenu($scope.selectedLanguage);
        });

Comments

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.