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.
Related
I'm trying to add some data structures (linkedList, Graph) implemented in pure js and use them in a Service.
I'm sure there is a better way than statically include libraries in your html page and attach them to the window object.
what's is the most clean way to 'inject' pure code in a Service?
We are creating a single page app with Angular routing.
The problem is that the Javascript with the controller(s) need to be referenced.
I want the js file to be downloaded dynamically on demand.
Is it mandatory to use a system like RequireJS ? Is there an alternative ?
AngularJS is just a wrapper over pure JS to make a system that's defined in its documentation (MVC, two-way binding, directive and so on). So, you can download the JS and bind the controller defined in the file to the angular app (ng-app). You don't need to use RequireJS to load the file, rather you can use pure JS to do the work.
Most people use requirejs but you can do it in pure JS.
stackoverflow.com/questions/7718935/load-scripts-asynchronously
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.
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.
I am using Angular JS. I wish to put unrelated code (ie, which is not a factory, service, controler, etc) in additional, separate modules, in a similar way one would with AMD or CommonJS.
At the time of writing, a search for 'Angular.JS make new module' using Google does not return any documentation on making Angular.JS modules.
I have a found a post on the Angular.JS Google Group that seems to indicate that instead of loading dependencies dynamically like other module systems, in Angular.JS dependencies must be inserted as additional script tags.
Is there any documentation on making Angular modules (which is not limited to controllers, services, or other angular concepts)?
Is the statement about script tags true? Do I need to manually add script tags for every module I may use?
Looking further into the various Angular boilerplate apps, apps manually load every part of their apps via script tags. Unlike other systems, Angular 'modules' don't take care of actually loading dependencies, they just inject them once already loaded.