Lazy load template and controller in angular UI-Router

22,180

Solution 1

Ok, thanks for the responses, but I have figured it out.

.state('log_in', {
url: '/log-in',
controller: 'controllerJsFile',
templateProvider: function() { return lazyDeferred.promise; },
resolve: {
    load: function($templateCache, $ocLazyLoad, $q, $http) {
        lazyDeferred = $q.defer();

        return $ocLazyLoad.load ({
          name: 'app.logIn',
          files: ['src/controllerJsFile.js']
        }).then(function() {
          return $http.get('src/htmlTemplateFile.tpl.html')
            .success(function(data, status, headers, config) {
              return lazyDeferred.resolve(data);
            }).
            error(function(data, status, headers, config) {
              return lazyDeferred.resolve(data);
            });
        });
    }
},
data: {
  public: true
}

})

So, after some more reading, I realized I had an issue with my promises. We create one called lazyDeferred which is the one to be returned to templateProvider and is declared as a global variable. templateProvider waits for the promise to be fulfilled.

After we load our controller, we create an XHR/ $http request to retrieve the template file. $http.get is a promise so we can return that, $ocLazyLoad.load also is a promise so we can return that as well. Finally, we just need to resolve the lazyDeferred one and that I think balloons through the promises and resolves all of them.

I apologize if this was not very clear, I'm not 100% sure of how this works.

Solution 2

In case you'd like to lazily load the controller, I would suggest follow these detailed answers:

In case we need to load dynamically the HTML template, it is much more easier. There is an example from this Q & A

(the working plunker)

$stateProvider
  .state('home', {
    url: '/home',
    //templateUrl: 'index5templateA.html',   (THIS WORKS)
    templateProvider: function(CONFIG, $http, $templateCache) {
        console.log('in templateUrl ' + CONFIG.codeCampType);

        var templateName = 'index5templateB.html';

        if (CONFIG.codeCampType === "svcc") {
             templateName = 'index5templateA.html';
        } 
        var tpl = $templateCache.get(templateName);

        if(tpl){
          return tpl;
        }

        return $http
           .get(templateName)
           .then(function(response){
              tpl = response.data
              $templateCache.put(templateName, tpl);
              return tpl;
          });
    },

You can check these as well:

Share:
22,180
Rjdlee
Author by

Rjdlee

A software engineer entrepreneur who has an obsession with baking bread.

Updated on July 09, 2022

Comments

  • Rjdlee
    Rjdlee almost 2 years

    I am attempting to lazy load a controller and template in my UI-Router router.js file, but am having difficulty with the template.

    The controller loads properly, but after that is loaded, we must load the template and this is where things go wrong.

    After ocLazyLoad loads the controller, we resolve an Angular promise which is also included in the templateProvider. The issue is instead of returning the promise (templateDeferred.promise) after the file is done loading, the promise is returned as an object.

    .state('log_in', {
        url: '/log-in',
        controller: 'controllerJsFile',
        templateProvider: function($q, $http) { 
          var templateDeferred = $q.defer();
    
            lazyDeferred.promise.then(function(templateUrl) {
            $http.get(templateUrl)
            .success(function(data, status, headers, config) {
                templateDeferred.resolve(data);
            }).
            error(function(data, status, headers, config) {
                templateDeferred.resolve(data);
            });
      });
      return templateDeferred.promise;
     },
     resolve: {
        load: function($templateCache, $ocLazyLoad, $q) {
            lazyDeferred = $q.defer();
    
            var lazyLoader = $ocLazyLoad.load ({
              files: ['src/controllerJsFile']
            }).then(function() {
              return lazyDeferred.resolve('src/htmlTemplateFile');
            });
            return lazyLoader;
        }
     },
     data: {
      public: true
     }
    })