2

I'm using ui router to manage routing, including for for submodules.

Here's the directory structure for the parent and child:

admin
   |
   | ---buildteams
   |         |
   |         |--- buildteams.js
   |         |--- buildteams.tpl.html
   |--- admin.js
   |--- admin.tpl.html

admin.js looks like this:

(function(adminModule) {

adminModule.config(function ($stateProvider) {
    $stateProvider
        .state('admin', {
            url: '/admin',
            views: {
                "main": {
                    controller: 'AdminController as vm',
                    templateUrl: 'admin/admin.tpl.html'
                }
            },
            data:{ pageTitle: 'Administration' }})

        .state('admin.buildteams', {
            url: '/buildteams',
            views: {
                "main": {
                    controller: 'AdminController as vm',
                    templateUrl: 'admin/admin.tpl.html'
                }
            },
            data:{ pageTitle: 'Build Teams' }
        });
});

adminModule.controller('AdminController', function ($scope,
                                                                $modal,
                                                                $state) {

    var vm = this;

    vm.itemSelected = function(item){

        if(item)
        {
            vm.template = item.template;
            vm.selected = {};

            vm.selected[item.name] = true;
        }

    };

    var init = function(vm) {

        vm.menuItems = [
            {
                name: "Build Teams",
                href: "admin.buildteams",
                template: "admin/buildteams/buildteams.tpl.html"
            }
        ];

        var current = $state.current.name;
        var item = vm.menuItems.find(function(x){
            return x.href===current;
        });

        vm.itemSelected(item);
    };

    init(vm);



});}(angular.module("myApp.admin", ['ui.router'])));

buildteams.js looks like this:

(function(adminModule) {

adminModule.controller('AdminBuildTeamsController', function ($scope,$modal) {

    var vm = this;

    var init = function(vm) {



    };

    init(vm);

});}(angular.module("myApp.admin")));

Here's where I register the modules:

(function(app) {

//configure routing
app.config(function ($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise('/home');
})

//inject http provider with authorization header
.config(function($httpProvider) {
        $httpProvider.interceptors.push(
            function($q, cachedUserService) {
                return {
                    'request': function(config) {
                        //ditch if the url is not api
                        var user = cachedUserService.getCurrentUser();
                        if (user) {
                            config.headers["Authorization"] = user.token;
                        }
                        return config || $q.when(config);
                    }                        
                };
            }
        );
    }
);

//register directives
app.directive("verticalMenu", function(){
    return {
        restrict: "E",
        templateUrl: "partialtemplates/verticalmenu.tpl.html"
    };
});

//not sure what this is
app.run(function () {});

//main controller
app.controller('AppController', function ($scope,
                                          cachedUserService,
                                          $modal,
                                          userAccountService,
                                          $location) {

    $scope.pageTitle = "myApp";

    $scope.user = cachedUserService.getCurrentUser();

    $scope.showLoginDialog = function()
    {
        var modalInstance = $modal.open({
            templateUrl: 'loginDialogContent.html',
            controller: 'LoginDialogController',
            windowClass: 'app-modal-window'
        });

        $scope.loginDialogOpened = true;

        modalInstance.result.then(function (user) {

            $scope.user = user;
            cachedUserService.setRememberEmail($scope.user.email);

        }, function () {

        });
    };

    if($scope.user == null)
    {
        $scope.user = {
            loggedIn : false
        };
    }

    //app controller watches
    $scope.$watch('user', function(newVal, oldVal){
        if(oldVal.loggedIn != newVal.loggedIn)
        {
            $scope.$broadcast('userLoggedIn', newVal);
        }
    });

    $scope.logout = function()
    {
        userAccountService.logout();
        $scope.user = {
            loggedIn : false
        };
        $location.path("/home");
    };

    $scope.unauthorizedNavigation = function(desiredPath)
    {
        $location.path("/home");
        $scope.showLoginDialog();
    };

    $scope.loginDialogOpened = false;

});}(angular.module("myApp", [
'myApp.home',
'myApp.about',
'myApp.useradmin',
'myApp.admin',
'templates-app',
'templates-common',
'ui.router.state',
'ui.router',
'ui.bootstrap'
])));

When I try to build, I get this error:

Error: [$injector:nomod] Module 'myApp.admin' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument. http://errors.angularjs.org/1.2.28/$injector/nomod?p0=myApp.admin at /Users/richard/Projects/myAppFrontEnd/vendor/angular/angular.js:78 Firefox 35.0.0 (Mac OS X 10.9): Executed 0 of 0 ERROR (0.272 secs / 0 secs)

I traced through it and discovered that angular is attempting to register the buildteams submodule before it registers the admin module. So the admin module is not there to add the buildteams submodule to.

One thing to note...this EXACT code is WORKING in another case in the same app. In fact this module/submodule code was copied from the useradmin files in the same project. (see the module registration above where I register useradmin and admin.

Any ideas? What's going on?

In what order does angular load the modules? Is there any way to specify that order?

EDIT

Here's the html for the parent module:

(function(adminModule) {

adminModule.config(function ($stateProvider) {
    $stateProvider
        .state('admin', {
            url: '/admin',
            views: {
                "main": {
                    controller: 'AdminController as vm',
                    templateUrl: 'admin/admin.tpl.html'
                }
            },
            data:{ pageTitle: 'Administration' }})

        .state('admin.buildteams', {
            url: '/buildteams',
            views: {
                "main": {
                    controller: 'AdminController as vm',
                    templateUrl: 'admin/admin.tpl.html'
                }
            },
            data:{ pageTitle: 'Build Teams' }
        });
});

adminModule.controller('AdminController', function ($scope,
                                                                            $modal,
                                                                            $state) {

    var vm = this;

    vm.itemSelected = function(item){

        if(item)
        {
            vm.template = item.template;
            vm.selected = {};

            vm.selected[item.name] = true;
        }

    };

    var init = function(vm) {

        vm.menuItems = [
            {
                name: "Build Teams",
                href: "admin.buildteams",
                template: "admin/buildteams/buildteams.tpl.html"
            }
        ];

        var current = $state.current.name;
        var item = vm.menuItems.find(function(x){
            return x.href===current;
        });

        vm.itemSelected(item);
    };

    init(vm);



});}(angular.module("myApp.admin", [
'ui.router'])));  

Here's the html for the submodule:

<div ng-controller="AdminBuildTeamsController as sub">
     Hello World!
</div>
9
  • Could you also show the html where you load the scripts? Commented Feb 15, 2015 at 1:40
  • What's strange is this exact code is working in the same project for another parent and it's sub modules. Commented Feb 15, 2015 at 2:02
  • It seems you were running this on Karma, are you sure you specified the admin module file to Karma? Angular always resolves dependencies in the sensible order, I don't think you can affect it. Commented Feb 15, 2015 at 2:08
  • Also, I might see another problem. I guess the form of angular.module without dependencies needs the module to be loaded at that moment in time. With html, you would fix this by re-organizing the script elements so that the module creation is first. With karma, you have to specify the creating file first in the list of files that karma should load. Commented Feb 15, 2015 at 2:12
  • Thanks. I am running Karma. But the error happens in the app too. If I load the parent view, it gives me that error and I can see it's loading the submodule first. Commented Feb 15, 2015 at 2:19

1 Answer 1

3
+200

As per our chat discussion, the problem was in the order that the browser / karma is loading the files. Grunt was used to find all the .js files, and it would try to parse the submodule file first because the folder name was alphabetically before the main .js file.

So running

angular.module("myApp.admin")

before

angular.module("myApp.admin", [])

caused the issue. Grunt was setup to load all the js files but loaded them in the wrong order. A solution was to rename the files such that the ordering is right.

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

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.