Could you help me to understand how to load controller in the example below before the view? It looks like the view is loaded just immediately while the controller is not loaded yet.
//app.js
$stateProvider.state('index', {
url: "/",
views: {
"topMenu": {
templateUrl: "/Home/TopMenu",
controller: function($scope, $injector) {
require(['controllers/top-menu-controller'], function(module) {
$injector.invoke(module, this, { '$scope': $scope });
});
}
}
}
});
//top-menu-controller.js
define(['app'], function (app) {
app.controller('TopMenuCtrl', ['$scope', function ($scope) {
$scope.message = "It works";
}]);
});
//Home/TopMenu
<h3>TopMenu</h3>
<div ng-controller="TopMenuCtrl">
{{message}}
</div>
On one project I used lazy loading of controllers and had to manually call a $digest on the scope to have it working. I guess that this behavior does not change with ui-router. Did you try that ?
I created working plunker here.
Let's have this index.html:
Let's observe the
main.js
- the RequireJS config:In fact, we only create aliases (paths) for our
ControllerNames
- and theirController_Scripts.js
files. That's it. Also, we return to require the app, but we will in our case use different feature later - to register lazily loaded controllers.what does the
deps: ['app']
mean? Firstly, we need to provide file app.js (the 'app' means findapp.js
) :this returned value is the one we can ask for in every async loaded file
How will we load controllers lazily? As already proven here for
ngRoute
angularAMD v0.2.1
We will ask angular for a reference to
$controllerProvider
- and use it later, to register controllers.This is the first part of our script.js:
As we can see, we just created the application 'app' and also, created holder
app_cached_providers
(following the angularAMD style). In the config phase, we ask angular for$controllerProvider
and keep reference for it.Now let's continue in script.js:
This part above shows two states declaration. One of them -
'home'
is standard none lazy one. It's controller is implicit, but standard could be used.The second is state named
"other"
which does target unnamed viewui-view=""
. And here we can firstly see, the lazy load. Inside of the resolve (see:)Resolve
With that in our suite, we know, that the controller (by its name) will be searched in angular repository once the resolve is finished:
Good, now, as mentioned above, the main contains this alias def
And that means, that the file "Controller_Other.js" will be searched and loaded. This is its content which does the magic. The most important here is use of previously cached reference to
$controllerProvider
the trick is not to use
app.controller()
but$controllerProvider.Register
Finally there is another state definition, with more narrowed resolve... a try to make it more readable:
Above we can see, that we resolve two controllers for both/all named views of that state
That's it. Each controller defined here
will be loaded via resolve and
$controllerProvider
- via RequireJS - lazily. Check that all hereSimilar Q & A: AngularAMD + ui-router + dynamic controller name?