Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: lazy loading controllers and content

In this simplified scenario, I have two files: index.htm, lazy.htm.

index.htm:

var myApp = angular.module('myApp', []); myApp.controller('embed',function($scope){     $scope.embed = 'Embedded Controller'; });                   <div ng-controller="embed">{{embed}}</div>     <div ng-include="'lazy.htm'"></div> 

lazy.htm

myApp.controller('lazy',function($scope){     $scope.lazy = 'Lazy Controller'; }); <div ng-controller="lazy">     {{lazy}} </div> 

The result is an error: "Argument 'lazy' is not a function, got undefined"

Using a function instead

lazy.htm

function lazy($scope) {     $scope.lazy = 'Lazy Controller'; } <div ng-controller="lazy">     {{lazy}} </div> 

This works until version 1.3 beta 14. In beta 15 was removed the global controller functions: https://github.com/angular/angular.js/issues/8296

So now, what is the better way to get angularized contents of lazy.htm dynamically?

UPDATE:

In this article (http://ify.io/lazy-loading-in-angularjs) I found another possible solution. The $controllerProvider allow us to register new controllers after angular bootstrap. Works like a charm. Tested in v1.3.0-beta.18

index.htm:

var myApp = angular.module('myApp', []) .controller('embed',function($scope){     $scope.embed = 'Embedded Controller'; }) .config(function($controllerProvider) {     myApp.cp = $controllerProvider; });  <div ng-controller="embed">{{embed}}</div>     <div ng-include="'lazy.htm'"></div> 

lazy.htm

myApp.cp.register('lazy',function($scope){     $scope.lazy = 'Lazy Controller'; }); <div ng-controller="lazy">     {{lazy}} </div> 

UPDATE 2:

Two other alternatives that works are:

lazy.htm

_app = $('[ng-app]').scope();     _app.lazy = function($scope) {     $scope.lazy = 'Lazy Controller'; }; 

OR

var $rootScope = $('[ng-app]').injector().get('$rootScope');         $rootScope.lazy = function($scope) {     $scope.lazy = 'Lazy Controller'; };  

But I believe these last two examples should not be used in production.

like image 568
Rodolfo Jorge Nemer Nogueira Avatar asked Aug 06 '14 19:08

Rodolfo Jorge Nemer Nogueira


People also ask

How is lazy loading implemented in AngularJS?

To enable lazy loading, we need to update the routing config to indicate that some modules will be loaded on route execution: import { ModuleWithProviders } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from '../home/home.

Does AngularJS support lazy loading?

AngularJS doesn't officially support lazy loading of components, services, etc. However, third party libraries such as ocLazyLoad provide this functionality. Lazy loading components is very simple with UI-Router and ocLazyLoad. The component is loaded and registered with ocLazyLoad, then the state is activated.

What is lazy loading content?

Lazy loading is a strategy to identify resources as non-blocking (non-critical) and load these only when needed. It's a way to shorten the length of the critical rendering path, which translates into reduced page load times.

Can you lazy load a component?

Lazy loading is the technique used in optimizing your web and mobile apps, this works by rendering only needed or critical user interface items first, then quietly rendering the non-critical items later. As we build code components the application grows, and the bundle gets very cumbersome in size.


2 Answers

You can also use the jquery with the resolve the $routeProvider

app.js

/* Module Creation */ var app = angular.module ('app', ['ngRoute']);  app.config(['$routeProvider', '$controllerProvider', function($routeProvider, $controllerProvider){  /*Creating a more synthesized form of service of $ controllerProvider.register*/ app.registerCtrl = $controllerProvider.register;  function loadScript(path) {   var result = $.Deferred(),   script = document.createElement("script");   script.async = "async";   script.type = "text/javascript";   script.src = path;   script.onload = script.onreadystatechange = function (_, isAbort) {       if (!script.readyState || /loaded|complete/.test(script.readyState)) {          if (isAbort)              result.reject();          else             result.resolve();     }   };   script.onerror = function () { result.reject(); };   document.querySelector("head").appendChild(script);   return result.promise(); }  function loader(arrayName){      return {       load: function($q){                 var deferred = $q.defer(),                 map = arrayName.map(function(name) {                     return loadScript('js/controllers/'+name+".js");                 });                  $q.all(map).then(function(r){                     deferred.resolve();                 });                  return deferred.promise;         }     }; }  $routeProvider       .when('/', {         templateUrl: 'views/foo.html',         resolve: loader(['foo'])     })     .when('/bar',{         templateUrl: 'views/bar.html',         controller: 'BarCtrl',         resolve: loader(['bar'])     })     .otherwise({         redirectTo: document.location.pathname     }); }]); 

/views/foo.html

<section ng-controller='FooCtrl'>     {{text}} </section> 

js/controllers/foo.js

/*Here we use the synthesized version of $controllerProvider.register  to register the controller in view*/ app.registerCtrl('FooCtrl',function($scope){     $scope.text = 'Test'; }); 

/views/bar.html

<section>     {{text2}} </section> 

js/controllers/bar.js

app.registerCtrl('BarCtrl',function($scope){     $scope.text2 = 'Test'; }); 
like image 159
André Betiolo Avatar answered Sep 24 '22 10:09

André Betiolo


////JConfig file--------

window.angularApp.config(function ($routeProvider,$controllerProvider,$compileProvider,$provide, azMessages) {  $routeProvider.when('/login', {              resolve: {                  load: ['$q', '$rootScope', function ($q, $rootScope) {                      var deferred = $q.defer();                      require([                           //load required Js file here                  ], function () {                     $rootScope.$apply(function () {                         deferred.resolve();                     });                 });                      return deferred.promise;                  } ]              }          });     $routeProvider.otherwise({ redirectTo: '/login' });      window.angularApp.components = {         controller: $controllerProvider.register,         service: $provide.service,         directive: $compileProvider.directive     } 

//contoller declaration

angularApp.components.controller('DiscussionController',[function(){  }]); 
like image 32
chirag Avatar answered Sep 26 '22 10:09

chirag