注册lazyloaded controller angularjs

时间:2017-02-22 17:24:25

标签: angularjs lazy-loading lazyload

我想像这样加载控制器:

.state({
    name: 'app.search',
    url: 'search?q&opts',
    templateUrl: '/templates/search.html',
    controller: 'SearchCtrl',
    resolve: {
        deps: function($util){
            return $util.load(['/ctrl/SearchCtrl.js']);
        }
    }
})

控制器加载但我收到以下错误,导致我认为控制器未注册:

Argument 'SearchCtrl' is not aNaNunction, got undefined

所以我的问题是,如图所示懒惰加载时如何注册控制器。

控制器定义为:

app.module('app').controller('SearchCtrl',function(){

});

我有什么办法可以强制控制器注册吗?

编辑应用程序已经完成并且所有工作都很精细。本问题只适用于LAZYLOADING。

问题与定义完全一样,控制器未注册,因为引导过程已经运行。我正在寻找一些在延迟加载时注册控制器的方法。

我的加载器功能($util.load()看起来像这样:

load: function (){

    if(arguments.length > 1){
        var items = arguments;
    }else{
        var items = arguments[0];
    }



    var _self = this;

    return $q(function(resolve,reject){
        if(items.length == 0){
            return resolve();
        }
        _self.async( items, function(item,next){
            if(item.indexOf('.js') != -1){
                _self.loadOne('script',item,next,function(err){
                    next(err);
                }); 
            }
            else if(item.indexOf('.css') != -1){
                _self.loadOne('link',item,next);
            }else{

                next();
            }
        },function(errors,results){
            $timeout(function() {
                $rootScope.$apply();// @Claies suggestion
                if(errors){
                    reject(errors);
                }else{
                    resolve();
                }
            });
        });
    });

},

1 个答案:

答案 0 :(得分:2)

我能够通过使用自定义函数覆盖angular.module()来自行解决,并且在此自定义函数中,我将对appInstance.controller的调用传递给$ controllerProvider.register()。它是有效的,我不确定它是多么合适,但只要它不会破坏任何东西我就不在乎。

var mod = angular.module('myModule',[]); //define my module

mod.config(['$controllerProvider',function($controllerProvider){

    mod._cRegister = $controllerProvider;//store controllerProvider onto the app instance.

    var mFunc = angular.module; // copy actual module function from angular

    //override angular.module with custom function
    angular.module = function(){

        var app = mFunc.apply(this,arguments);// proxy to the real angular.module function to get an app instance

        var cFunc = app.controller;//copy actual controller function from app instance

        app.controller = function(){

            mod._cRegister.register.apply(this,arguments); // try register on the controllerProvider instance as well


            return this;//return app instance so user can chain calls or whatever.

        }.bind(app);

        return app;//return app instance, just as angular does.

    }.bind(angular);    

}]);

//rest of module code (including the loader)

这很好用,但仅适用于控制器。以下是一个完整的示例,涵盖控制器,指令,组件,工厂,服务,值,常量和过滤器:

var mod = angular.module('myModule',[]);

mod.config(['$controllerProvider','$compileProvider','$filterProvider','$provide',function($controllerProvider,$compileProvider,$filterProvider,$provide){

    mod.$controllerProvider = $controllerProvider;
    mod.$compileProvider = $compileProvider;
    mod.$filterProvider = $filterProvider;
    mod.$provide = $provide;

    var map = {
        controller: ['$controllerProvider','register'],
        filter: ['$filterProvider','register'],
        service: ['$provide','service'],
        factory: ['$provide','factory'],
        value: ['$provide','value'],
        constant: ['$provide','constant'],
        directive: ['$compileProvider','directive'],
        component: ['$compileProvider','component']
    };

    var bootStrapped = [];

    var mFunc = angular.module;

    angular.module = function(){

        var app = mFunc.apply(this,arguments);

        //only override properties once.
        if(bootStrapped.indexOf(arguments[0]) == -1){
            for(var type in map){

                var c = mod;

                var d = map[type];

                for(var i=0;i<d.length;i++){
                    c = c[d[i]];// recurse until reaching the function
                }
                //now inject the function into an IIFE so we ensure its scoped properly
                !function(app,type,c){
                    app[type] = function(){
                        c.apply(this,arguments);
                        return this;//return the app instance for chaining.
                    }.bind(app);    
                }(app,type,c);
            }   
            bootStrapped.push(arguments[0]);//mark this instance as properly monkey patched
        }

        return app;

    }.bind(angular);    

}]);