Reputation: 13208
I'm trying to inject my controllers in AngularJS using the ui.router
resolve, but i'm having issues where the template is loading first. My app.js
is defined below:
var app = angular.module('app', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('view1', {
url: "/view1/",
templateUrl: "view1/view1.html",
resolve: {'': appendStaticFileToPage("view1/view1.js")}
})
.state('view2', {
url: "/view2/",
templateUrl: "view2/view2.html",
resolve: {'': appendStaticFileToPage("view2/view2.js")}
})
;
function appendStaticFileToPage(file) {
return function($q){
var script = document.createElement('script');
script.setAttribute('src', file);
document.getElementsByTagName('head')[0].appendChild(script);
};
}
});
When the user clicks on a particular link for a state, I inject the js
file for it into the browser. That part works fine. But the templateUrl
defines the template to be used and that always loads first. Since it defines an ng-controller
what happens is that the controller is being loaded, but since its not in the page yet, I get an error in the console that the controller couldn't be found. How can I achieve this?
I have created a simplified version of my code here:
http://plnkr.co/edit/X9uFOMIJq5tCn7VezSzT?p=preview
Is there a way to achieve what I am doing here?
EDIT
I previously had promises on my append code, which I'm showing below:
function appendStaticFileToPage(file) {
return function($q){
var deferred = $q.defer();
var script = document.createElement('script');
script.setAttribute('src', file);
document.getElementsByTagName('head')[0].appendChild(script).ready(function(){
deferred.resolve();
});
return deferred.promise;
};
}
When I do this, nothing happens. It doesn't load the template. It also doesn't show the console.log
statements I put in the controllers.
Upvotes: 2
Views: 285
Reputation: 95063
Since registering it with .controller isn't working, and I can confirm that the script is loading properly and executing, I tried instead injecting the $controllerProvider
service and registering the controller through there, and it works.
app.config(function($stateProvider, $urlRouterProvider, $controllerProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('view1', {
url: "/view1/",
templateUrl: "view1.html",
resolve: {'': appendStaticFileToPage("view1.js", "MyViewOneController")}
})
.state('view2', {
url: "/view2/",
templateUrl: "view2.html",
resolve: {'': appendStaticFileToPage("view2.js", "MyViewTwoController")}
})
;
function appendStaticFileToPage(file, controllerName) {
return function($q){
var deferred = $q.defer();
var script = document.createElement('script');
script.onload = function () {
$controllerProvider.register(controllerName, window[controllerName])
deferred.resolve();
};
script.onerror = function () {
deferred.reject();
};
script.setAttribute('src', file);
document.getElementsByTagName('head')[0].appendChild(script);
return deferred.promise;
};
}
});
I had to also update view1.js and view2.js as follows:
'use strict';
window.MyViewOneController = function($scope) {
console.log("Got to view 1");
};
Upvotes: 1