AngularJS: how angularjs executes? - angularjs

I'm sure this is boring - it has bothered me for some time now.
I wonder how AngularJS executes?
AngularJS provides some basics Module's Service, Provider and Factory and functions like app.run() and app.config().
What is the executing order of these modules and functions?
If I want to execute a function before the controller or directive executes where should I place it?

AngularJS first gathers everything. Maybe you have written custom directives and filters and external components, AngularJS will first gather each and every resource. Then, it would try to satisfy all the mentioned and required dependencies. So, if your module depends on any external module then, angular would first, load the external module and then would pass it to dependent module.
Now, for app.run() and app.config () methods.
A function passed to app.run() will be executed when all the modules have been loaded. It means all the modules, including external ones.
And a function passed to app.config() will be executed when current module have been loaded.
If I were you, I would place the redirect code in config() method.

Related

AngularJS: How to inject or require third parties library in directives?

What I am trying to do is my own angular directive. In this angular directive I would need a third party library.
Just to put an example I want to create a directive for tag clouds with d3.
In that case I have d3 accessible via d3 and then I would need to require the library d3.layout.cloud.js
I don't want to put my app plenty of scripts in the index so my questions is how to achieve that?
I mean, what is the correct way to inject a library only in a directive or at least just to load it only when I needed it
rather than loading it from the beginning?
Thanks
You need to get the script dynamically - that is when your directive is executed. The most basic way to do it is using pure JS.
var js_script = document.createElement('script');
js_script.type = "text/javascript";
js_script.src = "http://www.example.com/script.js";
document.getElementsByTagName('head')[0].appendChild(js_script);
Also you can use JQuery getScript.
If you need to go pure Angular, use $http to get the script and new Function to execute it.
Note
Please note that you can only inject an angular dependency in to an angular module. What you are talking about here is loading the script needed by the directive only when it is needed. You can't call that dependency injection. It is lazy loading.
To use a library, provide a src path of that library in base.html. After it, the library is going to be available throughout the application and you can use that library directly, without injecting or referencing it from anywhere
e.g.
To use lodash.js library, provide srcpath of library inside main.html.
In directive, controller and services function, use lodash directly using _(underscore) variable provided by lodash library.
You should create a module, inject the 3rd party library module into the module and then create your custom directive in that same module, and you will be able to access the 3rd party library from your directive just by injecting the 3rd party library (provider, service, etc) directly into the directive.
Regarding the part of not loading everything at the beginning, you might be interested in lazy loading.

AngularJS invokeQueue and configBlocks

AngularJs Source code deep dive - What does invokeQueue and configBlocks do during angularjs bootstrapping? I see they are passed to arguments for runInvokeQueue function inside loadModules.
configBlocks stores the list of services instantiated during module configuration:
angular.module("ng")._configBlocks[0][0]
invokeQueue stores the list of methods invoked after the module is loaded:
var foo = angular.module("ng");
foo.constant(alert)
foo._invokeQueue[0]
foo._invokeQueue[0][2][0]
The module definition is situated at the first lines of AngularJS source. As the documentation says, the life span of every module operation can be divided into two phases. The config phase and the run phase. The object exposed by calling the angular.module() constructor provides us with these two methods. The functionality of the run method is pretty obvious out of the source. It simply puts the config function passed to the private list of run blocks. The config method, on the contrary, is not so obvious. Here is, what the config method does:
The invokeLater private method inserts the combination of provider and its method to the internal module queue to be invoked later during the injector instantiation. The modules would be totally useless, if it weren't for the injector. The CreateInjector function is the concrete implementation and it has the private method loadModules.
The loadModules function does, among other, the kickoff of modules which are passed to it. It returns one array of all the run blocks of all modules which are dependent on each other. The injector calls them through its invoke method. Last but not least, the loadModules function, during its iteration through all dependent modules, calls their functions stored at _invokeQueue and _configBlock respectively. The run blocks are called in the last position. This means all services and methods of the modules are already exposed and ready for use. On the contrary, the config method only works with providers exposed by the module. The constructors of the providers are stored in the _invokeQueue of the module.
Two injectors
The first injector, that is not exposed publicly, is an injector of providers. The second one is an instance injector. The instance injector asks the provider cache for the constructors needed. Then it calls the proper part of the provider and creates an instance. The instance injector searches in the provider cache before asking for the provider injector. The module.provider method exposes the provider injector's provider method, which at a closer look says a lot about the life cycle of services.
Even other parts of angular constructs, like directives and controllers, are registered as providers in the provider's cache. The $compileProvider itself is then registered like any other provider through $provide.provider method. As a matter of fact, module.factory, module.service and module.provider store an instance in the provider cache as a first step. But it is an instance injector that we have at our disposal. The instance injector asks the provider cache as a first step and then calls the invoke method, which takes care of the dependencies.
References
Modules and injector
Configuring a Provider
fix(injector): invoke config blocks for module after all providers
Loading an AngularJS controller dynamically

Lazy loading AngularJS modules with RequireJS

Thanks to the great article from Dan Wahlin, I managed to implement lazy loading of Angular's controllers and services. However, there does not seem to be a clean way to lazy load independent modules.
To better explain my question, assume that I have an app would be structure as below without RequireJS:
// Create independent module 'dataServices' module with 'Pictures' object
angular.module("dataServices", []).factory("Pictures", function (...) {...});
// Create 'webapp' ng-app, with dependency to 'dataServices', defining controllers
angular.module("webapp", ['dataServices'])
.controller("View1Controller", function (...) {...})
.controller("View2Controller", function (...) {...});
Here is the sample app with RequireJS in Plunker:
http://plnkr.co/aiarzVpMJchYPjFRrkwn
The core of the problem is that Angular does not allow adding dependency to ng-app post instantiation. As result, my solution is to use angular.injector to retrieve the instance of Picture object to be used in my View2Controller. See js/scripts/controllers/ctrl2.js file.
This creates 2 problems for me:
The injected services runs outside of angular and therefore all async call must end with $scope.$apply()
Messy code where some object can be injected using standard angular syntax while others require the explicit use of injector.
Have any of you figured out how to lazy load independent module using RequireJS and somehow hook this module in angular so normal angular dependency injection syntax can be used?
Note:
The question is on lazy loading of independent module. One simple solution to this specific example is to create "Pictures" object using cached $providers during ng-app.config but that is not what I am looking for. I am looking for solution that works with 3rd party module such as angular-resource.
I finalized my own implementation called angularAMD and here is the sample site that uses it:
http://marcoslin.github.io/angularAMD/
It handles config functions and out of order module definitions.
Hopefully this can help other looking for something to help them with RequireJS and AngularJS integration.
Take a look at my project in GitHub: angular-require-lazy
This project is intended to demonstrate an idea and motivate discussions. But is does what you want (check expenses-view.js, it loads ng-grid lazily).
I am very interested in comments, ideas etc.
(EDIT) The ng-grid Angular module is lazy loaded as follows:
expenses-view.js is loaded lazily, when the /expenses route is activated
expenses-view.js specifies ng-grid as a dependency, so RequireJs loads ng-grid first
ng-grid is the one that calls angular.module(...)
In order to accomplish this, I replaced (proxied actually) the real angular.module method with my own, that supports laziness. See bootstrap.js and route-config.js (the functions initLazyModules() and callRunBlocks()).
This implementation has its drawbacks that you should be aware of:
Config functions are not implemented (yet). I do not know if it is possible to lazily provide config-time dependencies.
Order matters in definitions. If service A depends on B but A is defined after B in your module, DI wil fail. This is because the lazyAngular proxy executes definitions immediately, unlike real Angular that makes sure dependencies are resolved before executing the definitions.
It looks like the Node.js module ocLazyLoad defines a way of doing this lazy-loading, though I'm not sure how it fares, performance-wise, compared to the methods in the other answers or hard-coding the dependencies. Any info on this would be appreciated. One interesting thing is that the other answers need RequireJS to operate, while ocLazyLoad doesn't.
It looks like ocLazyLoad defines another provider that injects the dependency after the containing module has already been instantiated. It seems to do this by essentially replicating some low-level Angular behavior, like module loading and providing, hence why it looks so complicated. It looks like it adds just about every core Angular module as a dependency: $compileProvider, $q, $injector, ng, and so many more.

AngularJS - using requirejs inside factory

I'm trying to integrate angularjs with dojo.
I've decided to wrap creation of dojo objects in an external module, in order to leave my controller clean.
So I have a factory that exposes creation of an AndOrReadStore instance, for example, and then in the controller I use it to instantiate my dojo store.
Here is an example of what I'm trying to do:
http://plnkr.co/edit/EM0kXKWqZzZrlISvsOik
The problem is that the assignment to the store in the controller occurs before the code inside the requirejs block gets executed (and it doesn't make any difference if the async property of dojoConfig is true or false).
How can I use a factory method that is asynchronously? Could premise solve my problem?
Thanks,
Lior

Lazy-load external JavaScript in one of AngularJS controller

Some of my routes needs functionality from external JS. I don't want to load them all at once since those JS are needed only in certain routes (e.g. /upload needs some JS for photo uploading, /photos needs another JS for lightbox, /funny needs JS for animation stuff, etc).
What's the best practice for lazily loading those external JavaScripts?
Those routes can be accessed multiple times (e.g. user can go to /upload then /photos then /upload again)
In addition to what Alex has stated, if you will be lazy loading AngularJS artefacts such as controllers and directives, you would have to use the relevant provider to register them instead of the module API. Artefacts registered using the module API after the application has been bootstrapped, will not be available to the application. For example, you would define a lazy controller like this...
$controllerProvider.register('SomeLazyController', function($scope)
{
$scope.key = '...';
});
instead of this...
angular.module('app').controller('SomeLazyController', function($scope)
{
$scope.key = '...';
});
I have written a blog post detailing this as well as how to use the 'resolve' method that Alex speaks about, to implement lazy loading in AngularJS. http://ify.io/lazy-loading-in-angularjs/
The only way I know to handle cases like this is using the "resolve" method of a route. This method can be used to define a dependency to be loaded before the route's controller is instantiated. One of the different possible return types of this method is a promise. Thus you might use this to start loading your external JavaScript code asynchronously and return a promise that is resolved as soon as your external scripts are loaded.
The documentation for this can be found here: https://docs.angularjs.org/api/ngRoute/provider/$routeProvider in the "when" section.
#alex3683's answer is probably the correct AngularJS way, but I don't grasp the concept, so instead I make use of jQuery's getScript(). So, in CoffeeScript:
yourModule.factory 'foo', ->
$.getScript 'https://script-to-load', ->
# whatever you want to do once the script is loaded
And just call it from your controller. Since AngularJS services are lazy and singleton, this will only load the script once.

Resources