How to load controllers in AngularJS dynamically? - javascript

I have many controllers in app and I don't want to load them upfront as the combined JS becomes very heavy.
So I have tried following:
In my main app.js, I have route defined as below:
$routeProvider.when('/myaccount', {
templateUrl: 'my-account.html',
title: 'My Account'
})
The my-account-controller.js has controller defined like:
angular.module('myApp',[]).controller('my-account', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
}]);
And finally in my-account.html, I have a script tag which should load the controller syncronously before using it. I am attaching that contorller with ng-controller directive:
script src='/assets/my-account-controller.js'
<div class="container" ng-controller='my-account'>
...
</div>
The problem is somehow, Angular can not identify my-account as controller and it throws following error:
Error: [ng:areq] Argument 'my-account' is not a function, got undefined
Can someone tell me what is the missing piece?

You should use UpperCamelCase in your controller name, and i don't know if you already have defined myApp, if yes, you should remove the second argument from the module method since it will reset the dependencies:
so this -> angular.module('myApp',[]) should be -> angular.module('myApp')
angular.module('myApp').controller('MyAccount', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
}]);
And in your view:
<script src='/assets/my-account-controller.js'
<div class="container" ng-controller='MyAccount'>
...
</div>
And the route:
$routeProvider.when('/myaccount', {
templateUrl: 'my-account.html',
title: 'My Account',
controller: 'MyAccount'
});
You can read more about angular best practices here

This is not the proper way to do it. You have to declare your controller in the route you are using such as
$routeProvider.when(''/myaccount'', {
templateUrl: 'my-account.html',
controller: 'my-account',
title: 'My Account'
})

Related

Angular directive error : Unable to load template from templateUrl - fails when I load template via 'templateUrl' (continuous loading in browser)

I'm not sure why it shows below warnings in console and infinitely loads page, I'm just calling a template which is actually calling another directly in which I'm calling another html with templateUrl. Below is my code. Thanks in advance.
route file, which will load step-1.tpl.html on get-started/1
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/get-started/1', {
templateUrl: 'get-started/step-1.tpl.html',
});
}])
step-1.tpl.html - file in which I'm using my directive when above url is loaded
<div ng-controller="addWebsite">
<div step1></div>
</div>
my directive code
angular.module('add-website', [])
.controller('addWebsite', ['$scope', function($scope) {
$scope.customer = {
name: 'Naomi',
address: '1600 Amphitheatre'
};
}])
.directive('step1', function() {
return {
restrict: 'AE',
templateUrl: 'add-website/step1.html'
};
});
add-website/step1.html
<div>Name: {{customer.name}} Address: {{customer.address}}</div>
I'm getting this error when I hit /get-started/1.
please include angular-route.js and inject 'ngRoute' in module dependency
In your .config file, what does your angular.module() declaration look like? At a guess I'd say you're doing something like you have for your controllers, like this:
angular.module('add-website', [])
Only have one like this, the one on your controller for example should look like this:
angular.module('add-website')
But Nishant is also right, you need to inject ngRoute too.
It was actually a path issue! :( get-started/step-1.tpl.html should be shared/get-started/step-1.tpl.html. Thanks!

AngularJS ngRoute - Rendering template along with Angular Controller the $routeProvider is pointing

I'm rendering template using ngRoute - $routeProvider and I'm trying to render respective controller along with the template. $routeProvider is pointing to that controller and so it gives me an error controller is undefined because I think the App is trying to call the controller before it receives the template.
The templateCtr definition is in the separate JS file.
app.js
...
$routeProvider
.when('/template', {
templateUrl: '/template.html',
controller: 'templateCtr'
})
;
template.html
...
<script src="templateCtr.js"></script>
templateCtr.js
var myApp = angular.module('myApp'); //Getting module reference
myApp.controller('templateCtr', ['$scope', function($scope){
...
}]);
I also came across resolve property using which can load data to be used in controller before view is generated but for that too controller has to present in the memory.
Someone please point me to the correct direction. Thanks!

Angular UI-router, controller is undefined

I am kind of new to the AngularJS framework and I am trying to migrate my test project using the standard router to use the UI-router, but I get the following error:
Error: [ng:areq] Argument 'mainCtrl' is not a function, got undefined
What I have done so far is:
Controller:
// mainCtrl.js
angular.module("sm-web")
.controller('mainCtrl',['$scope',
function($scope) {
...
}]);
Router:
angular.module('sm-web', ['ui.router'])
.config(['$stateProvider', '$urlRouterProvider', function( $stateProvider, $urlRouterProvider ) {
$urlRouterProvider.otherwise('root');
$stateProvider
.state('root', {
url: '',
templateUrl: path + 'ng/sm/view/main.html',
controller: 'mainCtrl'
});
}]);
Index:
<body ng-controller="mainCtrl">
<main-menu></main-menu>
<div class="container">
<div ui-view></div>
</div>
</body>
This works when I use the standard router, but not with the UI-router. Does anyone have any idea of what I am doing wrong?
It seems you have an issue w/the order you declare things. For you to declare the module "sm-web" you need to do this:
angular.module('sm-web', ['ui.router']);
Note that the presence of that 2nd array argument is what tells Angular that you're declaring the module (eg. creating a new module). When you leave that 2nd argument out, you're retrieving the module you previously declared.
So with that in mind, look at how it all is coming together in your code:
To declare the controller, you retrieve the module "sm-web" (by leaving off the 2nd array arg).
When configuring the router states, you declare a new module "sm-web". But note that immediately after you declare this new module, you try to register a state with the controller named "mainCtrl" -- but that doesn't exist yet.
You need to create the module somewhere before doing all of the above. After creating the module, then register the controller on the module. Finally, with the controller defined, then you can register the state that uses the controller.
There's too many ways to solve this ordering problem, so I'm not going to suggest anything further. It depends on what files the code lives in and the order you load those files in index.html.
In order to avoid your problem change your code by the following code:
// mainCtrl.js
angular.module("sm-web")
.controller('mainCtrl',['$scope',
function($scope) {
...
}]);

Trying to get my Resolve to inject into my controller to be able to inject into the HTML

This is my index.js file
'use strict';
angular.module('wildenglish', ['ngAnimate', 'ngTouch', 'restangular', 'ngRoute', 'ui.bootstrap'])
.config(function ($routeProvider, RestangularProvider) {
RestangularProvider.setBaseUrl('https://www.googleapis.com/calendar/v3/calendars/googleCalendarID');
$routeProvider
.when('/', {
templateUrl: 'app/main/main.html',
controller: 'MainCtrl',
resolve: {
calendarEvents: function(Restangular){
return Restangular.one('eventsAUTHKEY').get();
}
}
})
.otherwise({
redirectTo: '/'
});
})
And my main controller.js
'use strict';
angular.module('wildenglish')
.controller('MainCtrl', function(Restangular, calendarEvents) {
var self = this,
events = calendarEvents,
items = events.items;
});
The Error I'm receiving when I try to use in the HTML is:
Error: [$injector:unpr] Unknown provider: calendarEventsProvider <- calendarEvents <- MainCtrl
So I am trying to figure out how I can utilize the information that I am getting back from that Promise which I can log in the console to be accessible to the HTML via the controller
Do I need a service or factory? and where would that go?
Thank you in advance for your help
Assign the events returned by the resolved promise to your controller scope. You'll need to change the depencies your injecting into your controller. You can leave out Restangular since you are resolving your promise in your route but you do need $scope:
angular.module('wildenglish').controller('MainCtrl', function($scope, calendarEvents) {
// i'm assuming the following logs your events to your console
// if not you're having a problem with your Restangular request
console.log(calendarEvents);
// Assign calendarEvents to your $scope
$scope.events = calendarEvents;
});
Now you can use the events in your HTML template (assuming each event has a property called 'name'):
<ul>
<li ng-repeat="event in events">{{event.name}}</li>
</ul>
Sorry, I missed the answer above which is already the correct answer.
There was a similar problem here:
AngularJS, resolve and unknown provider
Basically if you are using the routeProvider to assign your controller in your script file you cannot use ng-controller in your template.

AngularJS calling a controller from a directive

I have a model called 'user', 'user' has a controller called 'login' and a directive called 'userMenu', what I'm trying to achieve is that the userMenu directive uses the controller 'login' that's available in the module. Maybe I don't understand well how the modules and directives should work but I'm doing the following:
First, I define my controller like this:
angular.module('user', []).
controller('login', ['$scope', '$http', function($scope, $http){
$scope.logIn = function(){
//Do something...
}
}
Then, in my directive...
angular.module('user', []).
directive('userMenu', function(){
return {
priority: 0,
templateUrl: 'app/includes/user/menu.html',
replace: true,
restrict: 'A',
controller: 'login',
}
});
But the I get this:
Error: Argument 'login' is not a function, got undefined
Would you please guide me on the use of directives and controllers within modules?
The problem is that you are re-defining the user directive while preparing your directive. I presume that you wanted to register both a controller and a directive on the same module. If so you can register your directive like this:
angular.module('user').directive('userMenu', function(){
return {
...
}
});
Notice that there is no second argument ([]) to the call of angular.module which means that you want to retrieve an instance of already defined module instead of defining a new one.

Categories