At work we use a global module/main-app
<html ng-app="mainApp" />
First of all, is it good or bad to use a global module?
Second, I don't want to load all dependencies in this global module so I want to use a lazy loader, but what do you think of this solution?
// Set my module as main module
$("#ng-app").attr("ng-app", "myModule");
// Load the global module and another directive
var app = angular.module('myModule', ["mainApp", "angucomplete"]);
I want to mention that I am using AngularJS with CodeIgniter so I'm loading the JS script in view rather than include it in module dependencies.
I'm using lazy load because I use require.js... if you need, you can put at end of your js:
angular.bootstrap(document, ['mainApp']);
See this sample on: jsbin
I am trying to integrate angularjs app with requirejs. I want to preload templates and controllers on-demand. In my example:
http://plnkr.co/edit/vIps7t92OFzA5RXoTjvI?p=preview
I init controller SocialController inside the app.js and I need to load dynamically StreamController inside the SocialController. Unfortunately I am getting an exception, see browser console.
Argument 'StreamController' is not a function, got undefined
If I remove from SocialController
angular.module('sampleTest').controller('StreamController', StreamController);
and add it to app.js, it works but in this case requirejs will preload it right at the beginning and not when I need, inside the SocialController on demand.
Here is an answer. Looks like angular does not allow instantiating any new services or controllers later on, after the app startup. So the code below I had to add to app.js files at the bottom, after all the controller and services are init. This is a hack but fixes the problem for lazy loading with requirejs.
See my link to plunkr with the fix. Now there are no exception and StreamController is lazy loaded and init after the startup.
sampleApp.config(
function (
$controllerProvider,
$compileProvider,
$filterProvider,
$provide
) {
sampleApp.controller = $controllerProvider.register;
sampleApp.directive = $compileProvider.directive;
sampleApp.filter = $filterProvider.register;
sampleApp.factory = $provide.factory;
sampleApp.service = $provide.service;
}
);
I have a JS file with Angular controllers etc. that are used on lots, or many pages. It starts with the line:
var fb = angular.module( 'fb', ['fb.controllers','fb.directives','fb.services','ui.bootstrap'] );
The JS file also contains Angular controllers etc. that are used rarely, that depend on 'ui.bootstrap'.
What solutions are available to move my Angular code to separate JS files and only including the dependency 'ui.bootstrap' when I need it?
You are right, it is strongly recommended to separate such things and also to create one file per controller/directive/filter/etc.
Once you registered module you can use it in the other js files. Angular automatically resolve dependencies.
For example, in fb-controllers.js you register 'fb.controllers' module which depends on 'ui.bootstrap':
angular.module('fb.controllers', ['angular.ui']);
in fb-directives.js you register 'fb.directives' module which ot depends on 'ui.bootstrap':
angular.module('fb.directives', []);
then in app.js you register your main module with dependencies on other:
var fb = angular.module( 'fb', ['fb.controllers','fb.directives']);
I have an angular.js app that is declared with ng-app="audioApp" in the <body> tag of the html file.
If I have an angular.module call in one javascript file:
var app = angular.module('audioApp', []);
Can I make another identical angular.module call in a different javascript file? My application is mysteriously breaking with this second angular.module call, so it seems I can not have this call twice.
Any suggestions to a solution would be appreciated.
Yes. You need to omit the , [] part.
var app = angular.module('audioApp');
That'll grab a reference to the module, rather than redefine it.
What I like to do is keep a module.js file, which comes before any files which depend on the module or extend it.
audioApp.js
var app = angular.module('audioApp', ['some', 'deps']);
someDirective.js
var app = angular.module('audioApp');
app.directive(...);
someController.js
var app = angular.module('audioApp');
app.controller();
Is there a way to inject a late dependency to an already bootstrapped angular module? Here's what I mean:
Say that I have a site-wide angular app, defined as:
// in app.js
var App = angular.module("App", []);
And in every page:
<html ng-app="App">
Later on, I'm reopening the app to add logic based on the needs of the current page:
// in reports.js
var App = angular.module("App")
App.controller("ReportsController", ['$scope', function($scope) {
// .. reports controller code
}])
Now, say that one of those on-demand bits of logic also requires their own dependencies (like ngTouch, ngAnimate, ngResource, etc). How can I attach them to the base App? This doesn't seem to work:
// in reports.js
var App = angular.module("App", ['ui.event', 'ngResource']); // <-- raise error when App was already bootstrapped
I realize I can do everything in advance, i.e -
// in app.js
var App = angular.module("App", ['ui.event', 'ngResource', 'ngAnimate', ...]);
Or define every module on its own and then inject everything into the main app (see here for more):
// in reports.js
angular.module("Reports", ['ui.event', 'ngResource'])
.controller("ReportsController", ['$scope', function($scope) {
// .. reports controller code
}])
// in home.js
angular.module("Home", ['ngAnimate'])
.controller("HomeController", ['$scope', '$http', function($scope, $http){
// ...
}])
// in app.js, loaded last into the page (different for every page that varies in dependencies)
var App = angular.module("App", ['Reports', 'Home'])
But this will require I initialize the App everytime with the current page's dependencies.
I prefer to include the basic app.js in every page and simply introduce the required extensions to each page (reports.js, home.js, etc), without having to revise the bootstrapping logic everytime I add or remove something.
Is there a way to introduce dependencies when the App is already bootstrapped? What is considered the idiomatic way (or ways) to do this? I'm leaning towards the latter solution, but wanted to see if the way I described could also be done. thanks.
I solved it like this:
reference the app again:
var app = angular.module('app');
then push your new requirements to the requirements array:
app.requires.push('newDependency');
Simple...
Get an instance of the module using the getter like this:
var app = angular.module("App");
Then add to the "requires" collection like this:
app.requires[app.requires.length] = "ngResource";
Anyway, this worked for me. GOOD LUCK!
According to this proposal on the Angular JS google group this functionality does not exist as of this moment. Hopefully the core team decides to add this functionality, could use it myself.
If you wish to add multiple dependencies at once, you can pass them in push as follows:
<script>
var app = angular.module('appName');
app.requires.push('dependencyCtrl1', 'dependencyService1');
</script>
I realize that this is an old question, however, no working answer has yet been provided, so I decided to share how I solved it.
The solution requires forking Angular, so you can't use CDN anymore. However the modification is very small, so I am surprised why this feature doesn't exist in Angular.
I followed the link to google groups that was provided in one of the other answers to this question. There I found the following code, which solved the issue:
instanceInjector.loadNewModules = function (mods) {
forEach(loadModules(mods), function(fn) { instanceInjector.invoke(fn || noop); });
};
When I added this code to line 4414 in the angular 1.5.0 source code (inside the createInjector function, before the return instanceInjector; statement), it enabled me to add dependencies after bootstrapping like this $injector.loadNewModules(['ngCookies']);.
Since version 1.6.7 it is now possible to lazy load modules after the app has been bootstrapped using $injector.loadNewModules([modules]). Below is an example taken from AngularJS documentation:
app.factory('loadModule', function($injector) {
return function loadModule(moduleName, bundleUrl) {
return getScript(bundleUrl).then(function() { $injector.loadNewModules([moduleName]); });
};
})
Please read full documentation about loadNewModules as there are some gotchas around it.
There's also a very good sample app by omkadiri using it with ui-router.