Angularjs: Uncaught ReferenceError $rootScope is not defined - javascript

I am trying to run and got this message:
Uncaught ReferenceError: $rootScope is not defined at app.js line 12
here is my js/app.js
angular.module('addEvent', ['ngRoute'])
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider.when('/add-event', {
templateUrl: 'views/add-event.html',
controller: 'formCtrl',
controllerAs: 'eventCtl'
})
.otherwise({
redirectTo: '/'
});
$locationProvider.html5Mode(true);
}])
.run(['$rootScope', function() {
$rootScope.event = [];
}]);
this js/controller.js
angular.module('addEvent')
.controller('formCtrl', ['eventFactory', function(eventFactory) {
//$scope.event=[];
this.event = eventFactory.getAllEvents();
this.submitForm = function(form) {
eventFactory.createEvent(angular.copy(form), this.event);
// $scope.event.push(angular.copy(form));
console.log($scope.event);
}
}])
services/eventFactory.js
angular.module('addEvent')
.factory('eventFactory', function() {
var eventFactory = {};
var events = [];
eventFactory.getAllEvents = function() {
return events;
}
eventFactory.createEvent = function(event, eventList) {
events.push(event);
eventList = events;
return eventList;
}
return eventFactory;
})
And at index.html I added script this way
<script src="./js/jquery-1.12.4.js"></script>
<script src="./js/bootstrap.js"></script>
<script src="./js/angular.min.js"></script>
<script src="./js/angular-route.js"></script>
<script src="./js/app.js"></script>
<script src="./js/controller.js"></script>
<script src="./services/eventFactory.js"></script>

You need to inject $rootScope in the run() method
.run(['$rootScope',function($rootScope){
$rootScope.event=[];
}]);
instead of
.run(['$rootScope',function(){
$rootScope.event=[];
}]);

You forgot to include the $rootScope service in the run function as a parameter that's why you see the error Uncaught ReferenceError: $rootScope is not defined
angular
.module('demo', [])
.run(run)
.controller('DefaultController', DefaultController);
run.$inject = ['$rootScope'];
function run($rootScope) {
$rootScope.events = [];
console.log($rootScope.events);
}
function DefaultController() {
var vm = this;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
</div>
</div>

Related

How to Initialize third party JavaScript asynchronous library before loading AngularJS

I'm facing problem while initializing a third party JavaScript API (iHUB) inside RUN method of AngularJS. Currently the code is behaving in asynchronous mode. I want IHUB to first initialize and then AngularJS route/controller should get called. (Is it possible to make utilization of the callback method provided by IHUB ?)
var nameApp = angular.module('nameApp', ['ngRoute']);
nameApp.run(['$window', 'myService', function($window, myService) {
//initialize IHUB
var actuate= new actuate();
actuate.initialize('http://localhost:8700/iportal', settings.reqOps, "user", "pwd", callback);
function callback(){
alert('started!!');
}
}]);
nameApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/:tabname', {
templateUrl: 'pages/analyticsDetail.html',
controller: 'tabDetailCtrl'
}).
when('/:tabname/:reportName', {
templateUrl: 'pages/analyticsDetail.html',
controller: 'reportDetailCtrl'
}).
otherwise({
redirectTo: '/Buy Side Dashboard'
});
}]);
There is only one way to achieve a "real" before AngularJS initialization behavior by using angular.bootstrap();. This allows you to initialize your AngularJS application manually.
Note: You should not use the ng-app directive when manually bootstrapping your app.
> Fiddle demo
View
<div ng-controller="MyController">
Hello, {{greetMe}}!
</div>
Application
angular.module('myApp', [])
.controller('MyController', ['$scope', function ($scope) {
$scope.greetMe = 'World';
}]);
var actuateDummy = {
initialize: function (callback) {
setTimeout(callback, 2500);
}
};
actuateDummy.initialize(function () {
angular.element(function() {
angular.bootstrap(document, ['myApp']);
});
})
This is an other approach which uses the resolve state of ui-router. This service only initializes iHUB if it not has been initialized yet:
This service also returns the actuate object. In that way you can use it in your controller or components after init.
> Demo fiddle
View
<nav>
<a ui-sref="state1">State 1</a>
<a ui-sref="state2">State 2</a>
</nav>
<div ui-view></div>
AngularJS Application
var myApp = angular.module("myApp", ["ui.router"]);
myApp.config(function($stateProvider, $urlRouterProvider) {
$stateProvider.state("state1", {
url: "#",
template: "<p>State 1</p>",
controller: "Ctrl1",
resolve: {
iHubInit: function(iHubService) {
return iHubService.init()
}
}
}).state("state2", {
url: "#",
template: "<p>State 2</p>",
controller: "Ctrl2",
resolve: {
iHubInit: function(iHubService) {
return iHubService.init()
}
}
});
});
myApp.controller("Ctrl1", function($scope, iHubService) {
console.log("Ctrl1 loaded.");
});
myApp.controller("Ctrl2", function($scope, iHubService) {
console.log("Ctrl2 loaded.");
});
myApp.service('iHubService', ["$q", function($q) {
this.iHubServiceInitialized = false;
this.actuate = null;
this.init = function() {
if (!this.iHubServiceInitialized) {
//Init
var self = this;
var deferred = $q.defer();
this.actuate = new actuate();
//initialize
this.actuate.initialize('http://localhost:8700/iportal', settings.reqOps, "user", "pwd", function() {
self.iHubServiceInitialized = true;
deferred.resolve(self.actuate);
});
return deferred.promise;
} else {
return this.actuate;
}
}
}]);
Try to add a resolve attribute when configuring your route provider like below:
var nameApp = angular.module('nameApp', ['ngRoute']);
nameApp.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/:tabname', {
templateUrl: 'pages/analyticsDetail.html',
controller: 'tabDetailCtrl',
resolve: {
ihubInit: ['iHubService', function (iHubService) {
return iHubService.init();
}]
}
}).
when('/:tabname/:reportName', {
templateUrl: 'pages/analyticsDetail.html',
controller: 'reportDetailCtrl',
resolve: {
ihubInit: ['iHubService', function (iHubService) {
return iHubService.init();
}]
}
}).
otherwise({
redirectTo: '/Buy Side Dashboard'
});
}]);
nameApp.service('iHubService', ["$q", function($q){
this.init = function() {
var deferred = $q.defer();
var actuate= new actuate();
actuate.initialize('http://localhost:8700/iportal', settings.reqOps, "user", "pwd", callback);
function callback(){
deferred.resolve();
}
return deferred.promise;
}
}]);

Error: $controller:ctrlreg The controller with the name '{0}' is not registered

app.js
(function(){
'use strict';
angular
.module('app', ['ngRoute', 'ngCookies'])
.config(config)
config.$inject = ['$routeProvider', '$locationProvider'];
function config($routeProvider, $locationProvider){
$routeProvider
.when('/', {
controller: 'HomeController',
templateUrl: 'home/home.html',
controllerAs: 'vm'
})
}
})();
home.controller.js
(function () {
'use strict';
angular
.module('app')
.controller('HomeController', HomeController);
HomeController.$inject = ['UserService', '$rootScope'];
function HomeController(UserService, $rootScope) {
$rootScope.bodylayout ='main_page_que';
var vm = this;
}
})();
home.js
var app = angular.module('app', []);
app.controller('RedCtrl', function($scope) {
$scope.OpenRed = function() {
$scope.userRed = !$scope.userRed;
$scope.userBlue = false;
}
$scope.HideRed = function() {
$scope.userRed = false;
}
$scope.OpenBlue = function() {
$scope.userBlue = !$scope.userBlue;
$scope.userRed = false;
};
$scope.HideBlue = function() {
$scope.userBlue = false;
};
});
home.html
<div ng-controller="RedCtrl">
Show Red
<div hide-red="HideRed()" class="loginBox" ng-show="userRed"></div>
Show Blue
<div hide-blue="HideBlue()" class="loginBoxBlue" ng-show="userBlue"></div>
</div>
Index.html
<html lang="pl" ng-app="app">
<body class="{{bodylayout}}">
<div class="content">
<div ng-view style="margin:auto"></div>
</div>
<script src="//code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="//code.angularjs.org/1.6.0/angular.min.js"></script>
<script src="//code.angularjs.org/1.6.0/angular-route.min.js"></script>
<script src="//code.angularjs.org/1.6.0/angular-cookies.min.js"></script>
<script src="home.js"></script>
<script src="app.js"></script>
<script src="authentication.service.js"></script>
<script src="flash.service.js"></script>
<script src="user.service.local-storage.js"></script>
<script src="home/home.controller.js"></script>
</body>
</html>
Hey, this is part from application when I use ngRoute and dynamically add home.html, but I think I have wrong app.js or home.controller.js beacuse when I add external file home.js (when is ng-controller=""RedCtrl. I get error [$controller:ctrlreg] RedCtrl is not register. Have you ideas why? I am new in Angular and I think the main reason is lack of my knowledge.
You are overwriting app module in home.js thus getting the error
Use
var app = angular.module('app'); //Get previously defined module
instead of
var app = angular.module('app', []); //It declares new module
You also need to change the sequence of JavaScript files
<script src="app.js"></script>
<script src="home.js"></script>

Controller on angularJs

On the Link below on plunker, I am trying to do a simple page connecting view 1 to view 2.
On view 1 we can type a text which will be shown on View2.
My difficulty is trying to understand how I can connect the Controller1 mentioned in the $stateProviderState, to the
Controller1.js, to the view. I find it difficult to understand how the
factory works, how to do the injection.
Could anyone explain to me? Thank you.
Plnkr - Linking pages using ui-router
//app.module.js
var myApp = angular.module("myApp", ['ui.router']);
myApp.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.when("", "/View1");
$stateProvider
.state("View1", {
url: "/View1",
templateUrl: "View1.html",
view: {
controller: 'Controller1'
}
})
.state("View2", {
url: "/View2",
templateUrl: "View2.html",
view: {
controller: 'Controller2'
}
});
});
//Controller1.js
(function() {
'use strict';
angular
.module("myApp")
.factory('shareFactory', shareFactory)
.controller('Controller1', Controller1);
function Controller1(shareFactory, $scope, $http) {
var vm = this;
vm.textView1 = "SomethingToStartWith";
function getView1() {
shareFactory.getData()
.then(function(response) {
if (response.data) {
vm.textView1 = response.data;
console.log(vm.textView1);
} else {
console.log("Something was wrong");
return;
}
}, function(response) {
console.log("Entered this Error function");
});
}
}
});
//Index.html
<!DOCTYPE html>
<html data-ng-app="myApp">
<head>
<script src="https://code.angularjs.org/1.5.5/angular.js" data-semver="1.5.5" data-require="angularjs#1.5.5"></script>
<script data-require="angular.js#<2" data-semver="1.5.7" src="https://code.angularjs.org/1.5.7/angular.js"></script>
<script data-require="ui-router#1.0.0-alpha.5" data-semver="1.0.0-alpha.5" src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/1.0.0-alpha.5/angular-ui-router.js"></script>
<script src="app.module.js"></script>
<script src="Controller1.js"></script>
<script src="share.factory.js"></script>
</head>
<body >
<div class="header" ng-style="{background:'red'}">header</div>
<div data-ui-view=""></div>
<div class="footer" ng-style="{background:'blue'}">footer</div>
</body>
</html>
//share.factory.js
(function() {
angular
.module("myApp")
.factory('shareFactory', shareFactory);
function shareFactory() {
var data = '';
return {
getData: function() {
return data;
},
setData: function(newData) {
data = newData;
}
};
}
})();
Maybe code explains itself?
Below code forked from your initial plunk can be found here http://plnkr.co/edit/WLe3TLTa6DKWUQ21lK3P
JavaScript
angular.module('myApp', ['ui.router'])
.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.when('', 'view1');
// set up states
// no need to specify controllers in templates
$stateProvider
.state('view1', {
url: '/view1',
templateUrl: 'view1.html',
controller: 'Controller1',
controllerAs: 'vm'
})
.state('view2', {
url: '/view2',
templateUrl: 'view2.html',
controller: 'Controller2',
controllerAs: 'vm'
});
})
// factory, shared data
.factory('shareFactory', function($q) {
var data = 'initial value';
// mock $http using $q which returns
// resolved/rejected promise, as would $http
return {
getData: function() {
return $q.when(data); // resolve
},
setData: function(val) {
if (val.length > 0) {
data = val;
return $q.when(); // resolve
} else {
return $q.reject('value can\'t be empty'); // reject
}
}
};
})
.controller('Controller1', function(shareFactory, $state) {
var vm = this;
// because async
shareFactory.getData()
.then(function(data) {
vm.data = data;
});
vm.set = function(data) {
shareFactory.setData(data)
.then(function() {
vm.error = null;
$state.go('view2');
})
.catch(function(e) {
vm.error = e;
});
};
})
.controller('Controller2', function(shareFactory) {
var vm = this;
shareFactory.getData()
.then(function(data) {
vm.data = data;
})
.catch(function(e) {
console.log(e);
});
});
index.html
<body >
<div data-ui-view></div>
</body>
view1.html
<div>
<h1>view1</h1>
<label>Enter a value: </label>
<input type="text"
ng-model="vm.data">
<input type="button"
class="btn btn-default"
value="Go to view2"
ng-click="vm.set(vm.data)">
<pre ng-bind="vm.error"></pre>
</div>
view2.html
<div>
<h1>view2</h1>
The value set in view1 is: <b ng-bind="vm.data"></b>
<input type="button"
class="btn btn-default"
value="Go to view1"
ui-sref="view1">
</div>
Check the plunker. Injecting factory to controller, controller to main module and ui-routing
Check this
html
<div class="header" ng-style="{background:'red'}">header</div>
<div ui-view></div>
<div class="footer" ng-style="{background:'blue'}">footer</div>
main Js
var myApp = angular.module("myApp", ['ui.router','ConrollerApp']);
myApp.config(function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/View1");
$stateProvider
.state("View1", {
url: "/View1",
templateUrl: "View1.html"
})
.state("View2", {
url: "/View2",
templateUrl: "View2.html"
});
});
Controller
var ctrl=angular.module("ConrollerApp",["Factory"])
ctrl.controller("AppController",function($scope,AppFactory){
$scope.data=AppFactory.useData();
})
Factory
var factoryapp=angular.module("Factory",[])
factoryapp.factory("AppFactory",function(){
return{
useData:function(){
var x=10;
return x;
}
}
})`

AngularJS: Uncaught Error: $injector:modulerr Failed to instantiate module

I am trying to include several directives in as dependencies. Everything was working fine until I added a new directive called classificationview. its just an directive which will i will use somewhere later.
I am getting the error of :
Uncaught Error: [$injector:modulerr] Failed to instantiate module mainapp due to:
Error: [$injector:modulerr] Failed to instantiate module ald.classificationview due to:
Error: [$injector:nomod] Module 'ald.classificationview' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
The classification directive:
/**
*
*/
var classificationViewModule = angular.module('ald.classificationview',[]);
classificationViewModule.factory('classificationAPI',function(){
return {
getClassification:function($http){
//TODO add URL
var url = "/Classification?artifactId=6450"
return $http({
method: 'GET',
url: url
});
}
};
});
classificationViewModule.directive('classification', function () {
return {
restrict: 'EA',
scope: {},
replace: true,
link: function ($scope, element, attributes) {
},
controller: function ($scope, $http, classificationAPI) {
classificationAPI.getClassification($http).success(function(data,status){
//TODO Add required binding
$scope.artifactClassification = data;
}).error(function(data,status){
if (404==status){
alert("no text");
} else {
alert("bad stuff!");
}
});
},
//TODO add template url
templateUrl: "classificationview.html"
};
});
The main.js file :
var theApp = angular.module('mainapp', [
'ald.documentlist',
'ald.hierarchylist',
'ald.hierarchyviewer',
'ald.documentdisplay',
'ald.artifactlist',
'ald.classificationview',
'ngRoute'
]);
var controllers = {};
var directives = {};
controllers.tabsController = function ($scope, $location, $http) {
$scope.onClickTab = function (tabUrl) {
$scope.removePadding();
$location.$$search = {};
if (tabUrl == 'Hierarchy') {
$location.path("/hierarchy");
}
else if (tabUrl == 'Artifacts') {
$location.path("/artifacts");
}
else {
$location.path("/documents");
}
};
$scope.removePadding = function() {
$("#documentTab").css("padding", "0px");
$("#hierarchyTab").css("padding", "0px");
$("#artifactTab").css("padding", "0px");
};
};
controllers.IndexController = function ($scope, $http) {
};
controllers.DocumentsCentricViewCtrl = function ($scope, $http) {
$("#tabs").tabs( "option", "active", 0 );
};
controllers.DocumentDisplayViewCtrl = function ($scope, $http) {
$("#tabs").tabs( "option", "active", 0 );
};
controllers.HierarchyCentricViewCtrl = function ($scope, $http) {
$("#tabs").tabs( "option", "active", 1 );
};
controllers.ArtifactsCentricViewCtrl = function ($scope, $http) {
$("#tabs").tabs( "option", "active", 2 );
};
directives.panelTabs = function() {
return {
restrict: 'A',
link: function($scope, elm, attrs) {
var jqueryElm = $(elm[0]);
$(jqueryElm).tabs()
$scope.removePadding();
}
};
};
theApp.controller(controllers);
theApp.directive(directives);
theApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/documents', {
templateUrl: 'documentscentricview.html',
controller: 'DocumentsCentricViewCtrl'
}).
when('/hierarchy', {
templateUrl: 'hierarchycentricview.html',
controller: 'HierarchyCentricViewCtrl'
}).
when('/artifacts', {
templateUrl: 'artifactscentricview.html',
controller: 'ArtifactsCentricViewCtrl'
}).
when('/documents/:doc', {
templateUrl: 'documentdisplay.html',
controller: 'DocumentDisplayViewCtrl'
}).
otherwise({
/*
templateUrl: 'indexview.html',
controller: 'IndexController'
*/
redirectTo: '/documents'
});
}]);
The source of the javascript file is given in index file:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<meta name="layout" content="main"/>
<title>The Analyzer Engine and SDX Analysis UI</title>
%{--<script type="text/javascript">--}%
%{----}%
%{--</script>--}%
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<asset:link rel="icon" href="images/*" type="image/png"/>
<asset:stylesheet src="main.css"/>
<asset:javascript src="main.js"/>
<asset:javascript src="ald/documentlist/documentlist.js"/>
<asset:javascript src="ald/hierarchylist/hierarchylist.js"/>
<asset:javascript src="ald/hierarchyviewer/hierarchyviewer.js"/>
<asset:javascript src="ald/documentdisplay/documentdisplay.js"/>
<asset:javascript src="ald/artifactlist/artifactlist.js"/>
<asset:javascript src="ald/classificationview/classificationview.js"/>
</head>
<body>
<div ng-app="mainapp" class="tabWidth">
<div ng-controller="tabsController">
<div id="tabs" panel-Tabs>
<ul>
<li>Document</li>
<li>Hierarchy</li>
<li>Clauses, Terms and Titles</li>
</ul>
<div id="emptyDiv"></div>
</div>
</div>
<div ng-view></div>
</div>
</body>
</html>
It looks like the arguments to the link and controller functions in your directive are incorrect. Try this:
// 'scope' not '$scope'
link: function (scope, element, attributes) {
// Don't inject $http or your other dependency into the controller function. Use the //constructor function of the directive. See below:
controller: function ($scope)
classificationViewModule.directive('classification', function ($http, ClassificationAPI) {

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.
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';
});
////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(){
}]);
At first I utilized André Betiolo's answer. However, it does not always work becasue the ajax loading is non-blocking causing the view to sometimes request the controller prior to the script being loaded.
As a solution i forced the function not to return until all scripts successfully loaded. This is kind of hackish but makes sure the loads are successful prior to completing the resolve. It also allows for loading of multiple controllers.
app.js
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;
//jquery to dynamically include controllers as needed
function controllers(controllers){
var numLoaded = 0;
for (i = 0; i < controllers.length; i++) {
$.ajaxSetup({async:false});
$.getScript('js/controllers/' + controllers[i] + '.js').success(function(){
numLoaded++;
if (numLoaded == controllers.length) {
return true; //only return after all scripts are loaded, this is blocking, and will fail if all scripts aren't loaded.
}
});
}
}
$routeProvider
.when('/', {
templateUrl: 'views/foo.html',
resolve: {
load: function () {
controllers(['foo'])
}
}
})
.when('/bar',{
templateUrl: 'views/bar.html',
controller: 'BarCtrl',
resolve: {
load: function () {
controllers(['bar','foo']) //you can load multiple controller files
}
}
})
.otherwise({
redirectTo: document.location.pathname
});
}]);
/views/foo.html
<section ng-controller='FooCtrl'>
{{text}}
</section>
/views/bar.html
<section ng-controller='BarCtrl'>
{{text2}}
</section>
<section ng-controller='FooCtrl'>
{{text}}
</section>
/controllers/bar.js
app.registerCtrl('BarCtrl',function($scope){
$scope.text2 = 'Test';
});
You can have pure AngularJS lazy loading.
Create "LazyService":
var ng = angular.module('app');
ng.factory('lazyService', [ '$http', function($http) {
var jsPath = 'js/${ name }.js';
var promisesCache = {};
return {
loadScript: function(name) {
var path = jsPath.replace('${ name }', name);
var promise = promisesCache[name];
if (!promise) {
promise = $http.get(path);
promisesCache[name] = promise;
return promise.then(function(result) {
eval(result.data);
console.info('Loaded: ' + path);
});
}
return promise;
}
}
}]);
Then, define your config:
var ng = angular.module('app', [ 'ngRoute' ]);
ng.config([ '$routeProvider', '$controllerProvider', '$provide', function($routeProvider, $controllerProvider, $provide) {
// Lazy loading
ng.lazy = {
controller: $controllerProvider.register,
//directive: $compileProvider.directive,
//filter: $filterProvider.register,
factory: $provide.factory,
service: $provide.service
}
$routeProvider
.when('/', {
templateUrl: 'view/home.html'
})
.when('/vendor', {
templateUrl: 'view/vendor.html',
resolve: {
svc: [ 'lazyService', function(lazyService) {
return lazyService.loadScript('services/vendor');
}],
ctrl: [ 'lazyService', function(lazyService) {
return lazyService.loadScript('controllers/vendor');
}]
}
});
. . .
On "js/services/vendor.js", create service as:
var ng = angular.module('app');
ng.lazy.service('vendorService', [ function() {
. . .
On "js/controllers/vendor.js", create controller as:
var ng = angular.module('app');
ng.lazy.controller('vendorController', [ function() {
. . .
The "resolve" property on when defines which promises should be resolved before route loads.
The best way to do what you are asking is to instead use a directive and tie the controller and template together that way so its bound at the appropriate time. Currently, the binding it not happening in lazy.htm at the right time unless you declare a global function as you've shown in your second example.
Ideally - Angular will force you to separate HTML and JS as in newer versions this may be enforced more often.
You may have to use requireJS
http://solutionoptimist.com/2013/09/30/requirejs-angularjs-dependency-injection/
For the sake of trick can you try
ng-controller-controller="'lazy'"
or
In HTML
ng-controller-controller="myObject.controller"
Somewhere inject
$scope.myObject.controller = $controller('lazy', {$scope: $scope})
Try this ARI plugin for Angular JS. It helps you to lazy load the controller scripts on demand.
You also can use Directives to load your controller!
A example here:
https://gist.github.com/raphaelluchini/53d08ed1331e47aa6a87
I am sending you sample code. It is working fine for me. So please check this:
var myapp = angular.module('myapp', ['ngRoute']);
/* Module Creation */
var app = angular.module('app', ['ngRoute']);
app.config(['$routeProvider', '$controllerProvider', function ($routeProvider, $controllerProvider) {
app.register = {
controller: $controllerProvider.register,
//directive: $compileProvider.directive,
//filter: $filterProvider.register,
//factory: $provide.factory,
//service: $provide.service
};
// so I keep a reference from when I ran my module config
function registerController(moduleName, controllerName) {
// Here I cannot get the controller function directly so I
// need to loop through the module's _invokeQueue to get it
var queue = angular.module(moduleName)._invokeQueue;
for (var i = 0; i < queue.length; i++) {
var call = queue[i];
if (call[0] == "$controllerProvider" &&
call[1] == "register" &&
call[2][0] == controllerName) {
app.register.controller(controllerName, call[2][1]);
}
}
}
var tt = {
loadScript:
function (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(".shubham").appendChild(script);
return result.promise();
}
}
function stripScripts(s) {
var div = document.querySelector(".shubham");
div.innerHTML = s;
var scripts = div.getElementsByTagName('script');
var i = scripts.length;
while (i--) {
scripts[i].parentNode.removeChild(scripts[i]);
}
return div.innerHTML;
}
function loader(arrayName) {
return {
load: function ($q) {
stripScripts(''); // This Function Remove javascript from Local
var deferred = $q.defer(),
map = arrayName.map(function (obj) {
return tt.loadScript(obj.path)
.then(function () {
registerController(obj.module, obj.controller);
})
});
$q.all(map).then(function (r) {
deferred.resolve();
});
return deferred.promise;
}
};
};
$routeProvider
.when('/first', {
templateUrl: '/Views/foo.html',
resolve: loader([{ controller: 'FirstController', path: '/MyScripts/FirstController.js', module: 'app' },
{ controller: 'SecondController', path: '/MyScripts/SecondController.js', module: 'app' }])
})
.when('/second', {
templateUrl: '/Views/bar.html',
resolve: loader([{ controller: 'SecondController', path: '/MyScripts/SecondController.js', module: 'app' },
{ controller: 'A', path: '/MyScripts/anotherModuleController.js', module: 'myapp' }])
})
.otherwise({
redirectTo: document.location.pathname
});
}])
And in HTML Page:
<body ng-app="app">
<div class="container example">
<!--ng-controller="testController"-->
<h3>Hello</h3>
<table>
<tr>
<td>First Page </td>
<td>Second Page</td>
</tr>
</table>
<div id="ng-view" class="wrapper_inside" ng-view>
</div>
<div class="shubham">
</div>
</div>
Thank U

Categories