I am building a large Angular Application. I am trying to lazy load dependencies.
So my application module in app.js looks like
testApp = angular.module('SellerDashboard', [
'ui.bootstrap',
'ngRoute',
'chieffancypants.loadingBar',
'ngAnimate',
'route-segment',
'view-segment',
'Feature1.Index',
'Feature1.My_Listings',
'Feature1.My_Listings.Directives',
'Feature2.Debug',
'Feature2.Index',
'Feature3.Index',
'Feature3.Landing'
]);
Each of these modules have sub modules which has further dependencies.Each of the modules are in seperatefiles .An example file is as follows
var featureApp = angular.module('Feature1.My_Listings', ['Feature1.Services', 'Common.Services', 'CommonDebug.Services','angular-intro']);
listing_app.controller('my_listing', ['$scope', 'fkPaginator', '$routeParams', 'fkLogger', '$q','fkLoaderManager',function ($scope,fkPaginator, $routeParams, fkLogger, $q,fkLoaderManager) { //do somesthing})]);
So my app.js has no direct dependency on 'Feature1.Services' modules. It has dependency of Feature1.My_Listings module (which defines the controllers) which has further dependency on services modules.
[Feature1.Services defines the services has further dependency on other providers its requires]
Now,I do not want my Feature1.My_Listings to be loaded until I go the page that actually require some controller defined in 'Feature1.Services' .So if I am in "My_Listings" page I do not want to load fFeature2 and Feature 3 modules.
Implement lazy loading . The above link shows how to use resolve while changing routes.But then it also makes it mandatory to have all files under one module which is the app module and all controllers to be defined as app.controller("bla bla") using app as the global variable. But in my case I want to lazy load modules and include them dynamically based on the routes.
How do I go about it ?? It would be nice if somebody could help regarding how this can be achieved using requirejs.
So for a very large app is the above way correct for defining controllers,services ,etc or breaking them in to smaller modules like I did is the proper way ??
Related
I need a third party module in my angular app for the specific page only so i dont want to load those js files when they are not required
currently code is like this
angular.module('app', ['othermodule']);
but i want it like
angular.module('app',['']).
controller('ctrl'['module',function(module){
}]);
or any similar alternatives. How can modules be loaded conditionally ?
The first thing you will need to do is break your angular modules out into their own files. A simple example would be a seperate app.js that handles creating the app and routing, then controller.js and factory.js. Once you have a seperate file for each module you create the module with this syntax
angular.module('myapp.functionName.type', ['inject your custom module here'])
.whatever (controller, value, factory, etc)
You would then inject the myapp.functionName.type into the app.js
I am wondering how can I inject dependencies in more readable way in angular. I am more interested in AMD(requirejs) way. Like following:
define(function (require) {
var ModuleOne = require("ModuleOne"),
ModuleTwo = require("ModuleTwo");
var ThisModule = (function () {
// code here
})();
return ThisModule;
});
Is it possible to inject dependencies above way in angularjs or is there any better way to do it then current way in angularjs?
From the Angular JS official website
Angular modules solve the problem of removing global state from the
application and provide a way of configuring the injector. As opposed
to AMD or require.js modules, Angular modules don't try to solve the
problem of script load ordering or lazy script fetching. These goals
are orthogonal and both module systems can live side by side and
fulfil their goals.
Hence, purpose of both the libraries(RequireJS and AngularJS) is totally different. The dependency injection system built into AngularJS deals with the objects needed in a component; while dependency management in RequireJS deals with the modules or, JavaScript files.
In requireJS, Objects of loaded modules are cached and they are served when same modules are requested again. On the other hand, AngularJS maintains an injector with a list of names and corresponding objects. In this case, Object is served whenever it is referenced using the registered name.
Generally we inject dependencies in angularJS like
someModule.controller('MyController', function($scope,greeter){
});
If you want an alternative way to inject dependencies in angularJS, you may do something like.
var MyController = function($scope, greeter) {
// ...
}
MyController.$inject = ['$scope', 'greeter'];
someModule.controller('MyController', MyController);
Hope it helps!
I would to declare specific module because
I load on every page all my angular files..
It's huge.
I want to load specifically angular files on each page.
My app.js file that looks like this :
var testApp = angular.module(
'testApp', [
'MainCtrl',
'AdminCtrl',
'UserCtrl',
'ArticleCtrl',
'ArticleService',
'MediaService',
'UserService',
],
function($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
}
);
But it wants to declare modules that are no longer loaded.
So instead of making a specific app.js for each page I need..
Anyone has a better idea ?
Thank you.
You can make use of requirejs where modules will be loaded on demand.
A very nice tutorial how to achieve this:
Lazy loading angular components
I really enjoy the use of AMD to manage dependencies.
Now I'm getting started with Angular, in that case things become more complicated, because in one file we refer to a certain object that we admit to have already been created and this requires to make the script tags all organized and so on.
Another thing I noticed is that as the app grows there will be many script tags and more things to grant to be in order. I found ways to make AMD work with Angular.js, but I really didn't like it because it didn't seem natural.
What are the best practices to manage dependencies in Angular JS, making it easier to maintain the app as it grows?
I'd suggest Require.js which does implement AMD. There's a great example of how to configure your main.js (the entry point for a require.js application) and test-main.js (entry point for karma tests) here: https://github.com/tnajdek/angular-requirejs-seed.
Notes:
make sure to use paths and shim for dependent modules that you want to expose to your application but that are not available as require.js modules.
make sure you keep in mind the distinction between angular.js's concept of modules and require.js modules. Require.js modules are about describing file dependencies and loading in the correct fashion. Angular modules are about enabling dependency injection, once this loading is done correctly. You'll end up with code that looks like this example:
example app.js
define([
'angular', //as defined in the requirejs shim config
'filters', //as defined in the filters.js
'services', //as defined in services.js
'directives', //in directives.js
'controllers', //in controllers.js
'angularRoute',//as defined in the requirejs config
],function(angular,filters,services,directives,controllers,angularRoute){
'use strict';
//angular.js module definition syntax: Declare app level module which depends on filters,services,controllers,directives, and angular globals
var angularappModule = angular.module('angularapp', [
'ngRoute',
'angularapp.filters',
'angularapp.services',
'angularapp.directives',
'angularapp.controllers'
]);
angularappModule.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/angularapp', {templateUrl: 'partials/angularapp.html', controller: 'angularappCtrl'});
$routeProvider.when('/view2', {templateUrl: 'partials/partial2.html', controller: 'MyCtrl2'});
$routeProvider.otherwise({redirectTo: '/angularapp'});
}]);
return angularappModule;
});
I'm in process of learning Angular, so please forgive my naivety...
app.js in the angular-app example app references various dependencies in client/src/commmon/, such as services.breadcrumbs. How does Angular know to pull in these dependencies from the "common" directory? Is there some configuration I'm not seeing in this app?
Pertinent code:
angular.module('app', [
'ngRoute',
'projectsinfo',
'dashboard',
'projects',
'admin',
'services.breadcrumbs',
'services.i18nNotifications',
'services.httpRequestTracker',
'security',
'directives.crud',
'templates.app',
'templates.common']);
Take a look at https://github.com/angular-app/angular-app/blob/master/client/src/index.html
There you will see the following lines:
<script type="text/javascript" src="/static/jquery.js"></script>
<script type="text/javascript" src="/static/angular.js"></script>
<script type="text/javascript" src="/static/mongolab.js"></script>
<script type="text/javascript" src="/static/bootstrap.js"></script>
<script type="text/javascript" src="/static/<%= grunt.config.get('pkg.name') %>.js"></script>
This is where all of the packages are loaded. This is set up by Grunt, which is configured to concatenate JavaScript files together and create the files which are actually served. You should take a look at the Grunt configuration file (https://github.com/angular-app/angular-app/blob/master/client/gruntFile.js) to see how it is configured to do this. I don't know too much about Grunt yet, but if you know for what to look, you can find the configuration for concatenating various sets of files which are then placed in the distribution directory under the above referenced file names.
Angular dosen't have a dependency loader (yet).
all the script is being loaded from the first beginning. either as a bundle script, multiple <script> tags or being manual bootstrapped by another script loader
if I would create an angular app and want to use your code above, i would have to write
angular.module("myOwnApp", ["app"])
Now my app is a dependency of yours
and your app is depends on ngRoute, proj... so i have to load all your modules one way or the other
this is what I understand
Simply speaking, when you call:
angular.module('app',[
'ngRoute',
'projectsinfo'
]
angular will know you create a module app with dependencies of ngRoute and projectsinfo.
So when app is initiated, it will ask for these two dependencies from $injector, which is responsible for module dependencies.
So, when $injector is asked for these two module, it just look for them by the names, from something like a module POOL, $provide.
Simply put, when you define a module
angular.module('projectsinfo',[])
it actually just put a factory function, with the name 'projectsinfo' into the POOL. And the $injector will look for modules from it.
About the common derectory, since you load angular.js at the very beginning, so wherever you define a module by module, they all goto the same pool
In your example, services.breadcrumbs is not loaded from client/src/commmon. The scripts in client/source/common are loaded into the browser. On browser load, the scripts add themselves to the angular runtime (e.g. angular.module('service.breadcrumbs', [...])). Once a module is added to the angular runtime it is available for consumption by other angular modules.