KVISH
KVISH

Reputation: 13208

Issues loading controller angular.js

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

Answers (1)

Kevin B
Kevin B

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

Related Questions