javascriptangularjssystemjses6-modules

loading order issue when migrating an angular 1 app to use a moduleloader


I have to change one of our angular 1 applications to use a moduleloader (SystemJs), but I ran into an loading order issue, which I'm not sure how to solve it correctly.

This is how I'm loading the app (/app.js):

import angular from 'angular';
import './component/module';

angular.module('myApp',['component']);

// bootstrapping stuff...

Then there is the module definition with the routing stuff from the component (/component/module.js):

import angular from 'angular';
import 'angular-route';
import './CompController';

export default angular.module('component',['ngRoute']);

angular.module('component').config(function($routeProvider){
    $routeProvider.when('foo/bar',{
        templateUrl:'component/template.html',
        controller:'CompController'
    });
});

And the controller from the component (/component/CompController.js):

import angular from 'angular';

export default angular.module('component').controller('CompController',function(){
  // do something useful here...
});

When I run this, I get the following error:

Uncaught (in promise) Error: (SystemJS) [$injector:nomod] Module 'component' 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.

which is thrown in the "CompController", because when it's loaded, as a dependency of "component/module", the angular-module definition of 'component' hasn't been finished.

Can someone explain me how I can initialize the controller correctly, after the module is available? Am I making some basic faults?


Solution

  • Okay, I have the solution and it is stupid simple: I had to refactor the CompController.js to only export the controller function (the pure JavaScript function) instead of the controller object and pass it into angulars controller() function in the module.js, after the module is initialized.

    CompCotroller.js:

    export default function(){ // <= export only the pure function
        // do something useful here...
    }
    

    module.js:

    import angular from 'angular';
    import 'angular-route';
    import CompController from './CompController'; // <= load it...
    
    export default angular.module('component',['ngRoute']);
    
    angular.module('component').controller('CompController', CompController); // <= ...and create the controller here. That's it :)
    
    angular.module('component').config(function($routeProvider){
        $routeProvider.when('foo/bar',{
            templateUrl:'component/template.html',
            controller:'CompController'
        });
    });