Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I am trying to lazy load my controllers for my AngularJS app I built along side with requireJS. I have created a custom "lazyLoad" library that creates a resolve object in app.config() routes (also I am using ui-router). If I code the state (without my library) to look like so it works

define(['angular', 'lazyLoader', 'uiRouter'], function(angular, lazyLoader, uiRouter){

    var app = angular.module('myApp', ['ui.router']);

    app.config(function ($stateProvider, $urlRouterProvider, $controllerProvider, $compileProvider, $filterProvider, $provide) {


        window.lazy = {
            controller: $controllerProvider.register,
            directive: $compileProvider.directive,
            filter: $filterProvider.register,
            factory: $provide.factory,
            service: $provide.service
        };

        $urlRouterProvider.otherwise('/');

        $stateProvider
            .state('campaigns', {
                url:'/campaigns',
                views: {
                    "top-nav"  : {
                        templateUrl: 'views/home/top-nav.html',
                        resolve : {
                            load : ['$q', '$rootScope', function($q, $rootScope){
                                var d = $q.defer();
                                require(['../app/controllers/header-controller'], function() {
                                    $rootScope.$apply(function(){
                                        d.resolve();
                                    });
                                });
                                return d.promise;
                            }]
                        }
                    },
                    "fullpage": {
                        templateUrl: 'views/home/index.html',
                        resolve : {
                            load : ['$q', '$rootScope', function($q, $rootScope){
                                var d = $q.defer();
                                require(['../app/controllers/home-controller'], function() {
                                    $rootScope.$apply(function(){
                                        d.resolve();
                                    });
                                });
                                return d.promise;
                            }]
                        }
                        //controller: 'home-controller'
                    }
                }
            });

    });

    return app;

});

If I attempt to replace the resolve object with my library function it looks would look like this:

define(['angular', 'lazyLoader', 'uiRouter'], function(angular, lazyLoader, uiRouter){

and

.state('home', lazyLoader.route({
    url:'/',
    views: {
        "top-nav"  : {
            templateUrl: 'views/home/top-nav.html',
            controllerUrl: '../app/controllers/header-controller'
        },
        "fullpage": {
            templateUrl: 'views/home/index.html',
            controllerUrl: '../app/controllers/home-controller'
        }
    }
}));

lazyLoader.js

define(function () {
    'use strict';
    function LazyLoader() {}
    LazyLoader.prototype.route = function(config){
        var controllerPath;
        if(config && config.views){
            var singleView = Object.keys(config.views);
            for(var i in singleView){
                var viewName = singleView[i];
                controllerPath = config.views[viewName].controllerUrl;
                delete config.views.controllerUrl;
                config.views[viewName].resolve = {
                    load : ['$q', '$rootScope', function($q, $rootScope){
                        var d = $q.defer();
                        require([controllerPath], function() {
                            $rootScope.$apply(function(){
                                d.resolve();
                            });
                        });
                        return d.promise;
                    }]
                };
            }
        }
        return config;
    }
    return new LazyLoader();
});

Example Controller

define(['app/module'], function (module) {
    lazy.controller('header-controller', ['$scope', function ($scope) {
        // stuff here
    }]);
});

On a side note I plan on implementing something better than attaching lazy variable to window.

When I code the router like the first example it works. When I use my lazyLoader the one of the two views loads it's controller, the second view's controller's file is started to load (console.logs at the beginning show this) but it cannot resolve "module" in the example above.

link to error: AngularJS Error

Again this issue only happens when using my lazyloader which is producing the same resolve object that I have hard coded in for the version that works.

I have searched high and low and there are a lot of resources out there but I could not find anything that addressed this issue.

Any advice is appreciated!

share|improve this question

1 Answer 1

On the 'myApp' module definition, shouldn't you be returning app variable instead of myApp?

And to avoid exposing lazy to window, you could define it as a property of app variable, this way when you define new functions, you require app first and you can use it:

app.js:

app.lazy = {
        controller: $controllerProvider.register,
        directive: $compileProvider.register,
        filter: $filterProvider.register,
        factory: $provide.factory,
        service: $provide.service
    };
...
return app;

controller.js:

define(['app'], function (app) {
    app.lazy.controller('header-controller', ['$scope', function ($scope) {
        // stuff here
    }]);
});
share|improve this answer
    
Sorry that's an error in my question code. I am returning app currently and still experiencing the error. –  Jacob Carter Nov 15 '14 at 15:28
    
The rest looks fine to me, it's hard to say more without the rest of the code. But one thing I noticed, you're 'requiring' the controller file, but you're not assigning the controller's name to the states right? Try setting it: "top-nav" : { templateUrl: 'views/home/top-nav.html', controllerUrl: '../app/controllers/header-controller', controller: 'header-controller' }, –  frankies Nov 15 '14 at 20:07
    
I tried that too, sadly no results. Thanks for the input! –  Jacob Carter Nov 15 '14 at 20:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.