AngularJS Dynamic loading a controller
Asked Answered
H

1

15

I read a lot about lazzy loading, but I am facing a problem when using $routeProvider.

My goal is to load a javascript file which contains a controller and add a route to this controller which has been loaded previously.

Content of my javascript file to load

angular.module('demoApp.modules').controller('MouseTestCtrlA', ['$scope', function ($scope) {
    console.log("MouseTestCtrlA");
    $scope.name = "MouseTestCtrlA";
}]);

This file is not included when angular bootstap is called. It means, I have to load the file and create a route to this controller.

First, I started writing a resolve function which has to load the Javascript file. But declaring my controller parameter in route declaration gave me an error :

'MouseTestCtrlA' is not a function, got undefined

Here is the call I am trying to set :

demoApp.routeProvider.when(module.action, {templateUrl: module.template, controller: module.controller, resolve : {deps: function() /*load JS file*/} });

From what I read, the controller parameter should be a registered controller

controller – {(string|function()=} – Controller fn that should be associated with newly created scope or the name of a registered controller if passed as a string.

So I write a factory which should be able to load my file and then (promise style!) I whould try to declare a new route.

It gave me something like below where dependencies is an array of javascript files' paths to load :

Usage

ScriptLoader.load(module.dependencies).then(function () {
    demoApp.routeProvider.when(module.action, {templateUrl: 'my-template', controller: module.controller});
});

Script loader

angular.module('demoApp.services').factory('ScriptLoader', ['$q', '$rootScope', function ($q, $rootScope) {
        return {
            load: function (dependencies)
            {
                var deferred = $q.defer();
                require(dependencies, function () {
                    $rootScope.$apply(function () {
                        deferred.resolve();
                    });
                });
                return deferred.promise;
            }
        }
    }]);

Problem

I still have this javascript error "'MouseTestCtrlA' is not a function, got undefined" which means Angular could not resolved 'MouseTestCtrlA' as a registered controller.

Can anyone help me on this point please ?

Hormone answered 16/7, 2013 at 11:8 Comment(0)
H
26

Re-reading this article http://ify.io/lazy-loading-in-angularjs/ suggested to keep a $contentProvider instance inside Angular App.

I came up with this code in my app.js

demoApp.config(function ($controllerProvider) {
     demoApp.controller = $controllerProvider.register;
});

It enables me to write my controller as expected in a external javascript file :

angular.module("demoApp").controller('MouseTestCtrlA', fn);

Hope this can help !

Hormone answered 16/7, 2013 at 11:34 Comment(3)
Thanks so much, I have been searching for this for a while. Hopefully feature version of angular would find a way to expose register function so controllers can be loaded dynamically.Pyrosis
I would recommend you use angular-couch-potato. It lazy-registers controllers/factories/services/etc. A public app that I wrote with (Require+Angular+UIRouter) on github.Vanegas
@Hormone can you call angular.module("demoApp").controller('MouseTestCtrlA', fn); this from anywhere in the code to register new controllers? I have a directive that calls a remote server to retrieve a javascript file with a function, so I eval it to create dynamic controllers, but it seems the controllers are never registeredLentha

© 2022 - 2024 — McMap. All rights reserved.