conditionally inject device-specific Angular code at build time - angularjs

I've joined a project that uses Angular+Gulp+Webpack+Bower.
The project is built for different devices like so:
gulp deviceA
gulp deviceB
For each different device type, I will have a module called device.js that provides different versions of the same functions eg
device.foo();
device.bar();
I would like to conditionally inject the correct version of device.js at build time depending on the parameter passed to Gulp. device.js should be available application-wide and before the application starts.
If I tackle it in a non-Angular way, I could easily inject some self-executing code into index.html at build time that provides the device object globally. However, I want to make it more Angular-friendly so that I can eg use $rootScope to broadcast device events to the app.
My understanding is that an Angular Provider would suit my needs. Is that correct, and if so, what would be the correct way to inject the appropriate Provider at build time?

Related

Cookiecutter template testing, what is cookies.bake?

I am Trying to figure out how to write a test suite for my cookiecutter template.
after looking at the tests for the cookiecutter-django template in cookiecutter-django/tests/test_cookiecutter_generation.py I see that most of the test functions take a parameter called cookies. Within the test functions themselves there is a method call on whatever object is being passed in as the cookies parameter that is called bake.
I would like to know what this object is and where it's imported from?
In this case, cookies appears to be a fixture that is defined in pytest-cookies, as shown in the related pytest_cookies.py source code.
The cookies fixture actually appears to be a wrapper for cookiecutter itself. Additionally, the related cookies.bake() method can be used to generate a project based on your given cookiecutter template.
It may be interesting to note that pytest-cookies is a plugin for pytest, and as such, this plugin is accessible during testing as the related pytest documentation indicates:
If a plugin is installed, pytest automatically finds and integrates
it, there is no need to activate it.
Thus, because the requirements specify that pytest-cookies is to be used with cookiecutter-django, the cookies fixture from pytest-cookies should automatically be available during testing.

Angular: how do I init module (or service) with parameters?

I need to create a module that will be used by different applications.
Each application is using its own set of vars (application name, REST urls, ...).
How do I set inner variable, by the hosting application, in module (or in service)?
Need to init these parameters as soon as possible as the application loads.
Thanks.
In your module have a provider. That way the client application can bootstrap configuration.
Read the "Provider Recipe" section on angular's site for an example of this.
You should use the Provider recipe only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications.

What resources do angular modules share

I would like to have more theoretical understanding how angular modules work.
When I would create one module 'clientApp' and I 'register' controller, services, factories, scope etc..., inject other services, factories, scope into the controllers. What objects are known to the 'clientApp' module?
Angular Modules
An efficient, production-ready controllers by encapsulating our functionality in a single core unit called a module.
In Angular, a module is the main way to define an AngularJS app. The module of an app is where
we’ll contain all of our application code. An app can contain several modules, each one containing
code that pertains to specific functionality.
Using modules gives us a lot of advantages, such as:
• Keeping our global namespace clean
• Making tests easier to write and keeping them clean so as to more easily target isolated
functionality
• Making it easy to share code between applications
• Allowing our app to load different parts of the code in any order
The Angular module API allows us to declare a module using the angular.module() API method.
When declaring a module, we need to pass two parameters to the method. The first is the name of
the module we are creating. The second is the list of dependencies, otherwise known as injectables.
angular.module('myApp', []);
When writing large applications, we’ll create several different modules to contain our logic. Creating a module for each piece of functionality gives us the advantage of isolation in which to write and test large features.
Properties
Angular modules have properties that we can use to inspect the module.
name (string)
The name property on the modules gives us the name of the module as a string.
requires (array of strings)
The requires property contains a list of modules (as strings) that the injector loads before the
module itself is loaded.
Better Read
ng-book -
The Complete Book on AngularJS
Ari Lerner
Download ng-book

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.

Does Angular.JS have a module loader or do I need to use script tags?

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.

Resources