1

This question is a little strange and may be hard to grasp but I will try to explain as well I can. I have had to rewrite a mobile app using AngularJS as the previous version was not a true SPA. It was a JSP website that was styled to fit on a mobile device that uses ajax to call lightboxes, views, etc. Now I have to create new functionality for the new AngularJS application and also include this into the previous JSP version (the angularJS version isn't released yet). I don't want to have to do this twice so I have added AngularJS to the old version. I have registered an app on the body tag, registered some controllers and all is well except one thing. I have the following in my app.js file.

var oldMobile = angular.module('oldMobile', [
        'flow'
])

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

.controller('MainCtrl', function ($scope) {
    console.log('MainCtrl'); // this is shown in the console
})

.controller('UploadCtrl', function ($scope) {
    console.log('UploadCtrl'); // this is shown in the console
})

.controller('ProfileCtrl', function ($scope) {
    console.log('ProfileCtrl'); // this is NOT shown in the console
});

Now when the original view loads MainCtrl and UploadCtrl are registered as they are within the HTML, however ProfileCtrl isn't registered as this is content provided by a lightbox which is loaded dynamically after a user event (a click). When the lightbox is open where I have registered data-ng-controller="ProfileCtrl" within my HTML nothing is registered, nothing is written to the console, the Controller doesn't work. I try to register this by adding a script tag to the lightbox HTML like so

<script>
  angular.module("oldMobile").controller('ProfileCtrl');
</script>

but nothing happens. How can I get my module to register the ProfileCtrl when the lightbox is raised / called?

If I haven't explained this well please let me know and I shall add to my description.

Thanks in advance

1 Answer 1

2

Out of the box, Angular cannot lazy load its "artifacts" (controllers, directives etc). Anything you register after bootstrapping is accepted, meaning no error is thrown, but silently ignored by the dependency injection framework.

The solution is a bit complicated, first seen it here and implemented it also in angular-require-lazy for lazy loading with RequireJS.

The steps for registering controllers lazily are roughly as follows:

  1. Capture the $controllerProvider from a config block:

    var app = angular.module('app',[...]);
    var cachedControllerProvider;
    
    app.config(function($controllerProvider) {
        cachedControllerProvider = $controllerProvider;
    });
    

    (The global is not pretty, but this only demonstrates the principle.)

  2. Use the cachedControllerProvider to register controllers lazily; do not change the way normal controllers are registered:

    cachedControllerProvider.register('ProfileCtrl', function ($scope) {
        console.log('ProfileCtrl');
    });
    

    (In angular-require-lazy I modify the angular object to handle this transparently; this is an option for you too.)

  3. Make sure any scripts containing registrations of lazy controllers are executed before the templates that use those controllers!

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.